<commit_before>package cli

import (
	"fmt"
	"regexp"
)

// OptionType allows for the enumeration of different CLI option types.
type OptionType int

const (
	// None indicates that no option type is available.
	None OptionType = iota

	// Arg indicates that the option is an argument to be passed to the
	// executing code.
	Arg OptionType = iota

	// BuildArg indicates that the option is an argument to be passed to the
	// compiler if one is used for the target language.
	BuildArg OptionType = iota

	// Source indicates that the option is a source file.
	Source OptionType = iota

	// Include indicates that the option is a file or folder to be mounted
	// in the Docker container without passing it to the compiler or
	// executing code.
	Include OptionType = iota

	// SpecifyImage indicates that the option value should be used to
	// override the image worked out based on the file extension.
	SpecifyImage OptionType = iota

	// TargetDir indicates that the option specifies a custom location (i.e.
	// not the current working directory) to which the sources are
	// relatively specified.
	TargetDir OptionType = iota

	// UpdateFlag indicates that the option specifies that Docker images should
	// be manually updated before being used.
	UpdateFlag OptionType = iota

	// HelpFlag indicates that the option specifies the help flag.
	HelpFlag OptionType = iota

	// VersionFlag indicates that the option specifies the version flag.
	VersionFlag OptionType = iota

	// Extension specifies the override file extenision to use.
	Extension OptionType = iota
)

// CLI defines a data structure that represents the application's name and
// a map of the various options to be used when starting the container.
type CLI struct {
	Filename string
	Options  map[OptionType][]string
}

// ArgToOption takes two candidate strings and returns a tuple consisting of
// what type of option the strings define, the value of the option, how many
// of the strings it took to extract the option value, and a nillable error.
func ArgToOption(opt string, next string) (OptionType, string, int, error) {
	patternStandaloneA := regexp.MustCompile(`^-(a|-arg)$`)
	patternStandaloneB := regexp.MustCompile(`^-(b|-build-arg)$`)
	patternStandaloneI := regexp.MustCompile(`^-(i|-include)$`)
	patternStandaloneM := regexp.MustCompile(`^-(m|-image)$`)
	patternStandaloneE := regexp.MustCompile(`^-(e|-extension)$`)
	patternStandaloneC := regexp.MustCompile(`^-C$`)
	patternCombinationA := regexp.MustCompile(`^--arg=(.+)$`)
	patternCombinationB := regexp.MustCompile(`^--build-arg=(.+)$`)
	patternCombinationI := regexp.MustCompile(`^--include=(.+)$`)
	patternCombinationM := regexp.MustCompile(`^--image=(.+)$`)
	patternCombinationE := regexp.MustCompile(`^--extension=(.+)$`)
	patternSource := regexp.MustCompile(`^[^-_].+\..+`)
	patternUpdateFlag := regexp.MustCompile(`^-(-update|u)$`)
	patternHelpFlag := regexp.MustCompile(`^-(-help|h)$`)
	patternVersionFlag := regexp.MustCompile(`^-(-version|v)$`)

	switch {
	case patternStandaloneA.FindStringIndex(opt) != nil:
		return Arg, next, 2, nil
	case patternStandaloneB.FindStringIndex(opt) != nil:
		return BuildArg, next, 2, nil
	case patternStandaloneI.FindStringIndex(opt) != nil:
		return Include, next, 2, nil
	case patternStandaloneM.FindStringIndex(opt) != nil:
		return SpecifyImage, next, 2, nil
	case patternStandaloneE.FindStringIndex(opt) != nil:
		return Extension, next, 2, nil
	case patternStandaloneC.FindStringIndex(opt) != nil:
		return TargetDir, next, 2, nil
	case patternCombinationA.FindStringIndex(opt) != nil:
		return Arg, patternCombinationA.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationB.FindStringIndex(opt) != nil:
		return BuildArg, patternCombinationB.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationI.FindStringIndex(opt) != nil:
		return Include, patternCombinationI.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationM.FindStringIndex(opt) != nil:
		return SpecifyImage, patternCombinationM.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationE.FindStringIndex(opt) != nil:
		return SpecifyImage, patternCombinationE.FindStringSubmatch(opt)[1], 1, nil
	case patternUpdateFlag.FindStringIndex(opt) != nil:
		return UpdateFlag, "", 1, nil
	case patternHelpFlag.FindStringIndex(opt) != nil:
		return HelpFlag, "", 1, nil
	case patternVersionFlag.FindStringIndex(opt) != nil:
		return VersionFlag, "", 1, nil
	case patternSource.FindStringIndex(opt) != nil:
		return Source, opt, 1, nil
	default:
		return None, "", 0, fmt.Errorf("Unknown option: %s", opt)
	}
}

// ParseArgs take a string slice comprised of sources, includes, flags, switches
// and their values and returns a map of these types to a string slice
// of the values of each type of option.
func ParseArgs(args []string) map[OptionType][]string {
	if len(args) == 0 {
		return map[OptionType][]string{}
	}

	var next string
	if len(args) > 1 {
		next = args[1]
	}

	optionType, optionValue, nextIndex, _ := ArgToOption(args[0], next)

	if len(args) < nextIndex || nextIndex == 0 {
		return map[OptionType][]string{}
	}

	optionMap := ParseArgs(args[nextIndex:])
	optionMap[optionType] = append([]string{optionValue}, optionMap[optionType]...)
	return optionMap
}

// ParseOsArgs takes a string slice representing the full arguments passed to
// the program, including the filename and returns a CLI containing the
// filename and map of option types to their values.
func ParseOsArgs(args []string) CLI {
	return CLI{
		Filename: args[0],
		Options:  ParseArgs(args[1:]),
	}
}

// DisplayHelp takes a filename and prints the help information for the program.
func DisplayHelp(filename string) {
	fmt.Println("Name:")
	fmt.Printf("\t%s - Execute code in many languages with Docker!\n", filename)
	fmt.Println()
	fmt.Println("Usage:")
	fmt.Printf("\t%s [options]\n", filename)
	fmt.Println()
	fmt.Println("Options:")
	fmt.Printf("\t%-50s%s\n", "<source file>", "Execute source file")
	fmt.Printf("\t%-50s%s\n", "-C <dir>", "Specify source directory")
	fmt.Printf("\t%-50s%s\n", "--arg, -a <argument>", "Pass <argument> to the executing code")
	fmt.Printf("\t%-50s%s\n", "--build-arg, -b <build argument>", "Pass <build argument> to compiler")
	fmt.Printf("\t%-50s%s\n", "--include, -i <file|path>", "Mount local <file|path> in dexec container")
	fmt.Printf("\t%-50s%s\n", "--extension, -e <extension>", "Override the extension used to select image (required for stdin)")
	fmt.Printf("\t%-50s%s\n", "--specify-image, -s <docker image>", "Override the image used with <docker image>")
	fmt.Printf("\t%-50s%s\n", "--update, -u", "Update")
	fmt.Printf("\t%-50s%s\n", "--help, -h", "Show help")
	fmt.Printf("\t%-50s%s\n", "--version, -v", "Display version info")
}

// DisplayVersion prints the version information for the program.
func DisplayVersion(filename string) {
	fmt.Printf("%s 1.0.3\n", filename)
}
<commit_msg>version to v1.0.4<commit_after>package cli

import (
	"fmt"
	"regexp"
)

// OptionType allows for the enumeration of different CLI option types.
type OptionType int

const (
	// None indicates that no option type is available.
	None OptionType = iota

	// Arg indicates that the option is an argument to be passed to the
	// executing code.
	Arg OptionType = iota

	// BuildArg indicates that the option is an argument to be passed to the
	// compiler if one is used for the target language.
	BuildArg OptionType = iota

	// Source indicates that the option is a source file.
	Source OptionType = iota

	// Include indicates that the option is a file or folder to be mounted
	// in the Docker container without passing it to the compiler or
	// executing code.
	Include OptionType = iota

	// SpecifyImage indicates that the option value should be used to
	// override the image worked out based on the file extension.
	SpecifyImage OptionType = iota

	// TargetDir indicates that the option specifies a custom location (i.e.
	// not the current working directory) to which the sources are
	// relatively specified.
	TargetDir OptionType = iota

	// UpdateFlag indicates that the option specifies that Docker images should
	// be manually updated before being used.
	UpdateFlag OptionType = iota

	// HelpFlag indicates that the option specifies the help flag.
	HelpFlag OptionType = iota

	// VersionFlag indicates that the option specifies the version flag.
	VersionFlag OptionType = iota

	// Extension specifies the override file extenision to use.
	Extension OptionType = iota
)

// CLI defines a data structure that represents the application's name and
// a map of the various options to be used when starting the container.
type CLI struct {
	Filename string
	Options  map[OptionType][]string
}

// ArgToOption takes two candidate strings and returns a tuple consisting of
// what type of option the strings define, the value of the option, how many
// of the strings it took to extract the option value, and a nillable error.
func ArgToOption(opt string, next string) (OptionType, string, int, error) {
	patternStandaloneA := regexp.MustCompile(`^-(a|-arg)$`)
	patternStandaloneB := regexp.MustCompile(`^-(b|-build-arg)$`)
	patternStandaloneI := regexp.MustCompile(`^-(i|-include)$`)
	patternStandaloneM := regexp.MustCompile(`^-(m|-image)$`)
	patternStandaloneE := regexp.MustCompile(`^-(e|-extension)$`)
	patternStandaloneC := regexp.MustCompile(`^-C$`)
	patternCombinationA := regexp.MustCompile(`^--arg=(.+)$`)
	patternCombinationB := regexp.MustCompile(`^--build-arg=(.+)$`)
	patternCombinationI := regexp.MustCompile(`^--include=(.+)$`)
	patternCombinationM := regexp.MustCompile(`^--image=(.+)$`)
	patternCombinationE := regexp.MustCompile(`^--extension=(.+)$`)
	patternSource := regexp.MustCompile(`^[^-_].+\..+`)
	patternUpdateFlag := regexp.MustCompile(`^-(-update|u)$`)
	patternHelpFlag := regexp.MustCompile(`^-(-help|h)$`)
	patternVersionFlag := regexp.MustCompile(`^-(-version|v)$`)

	switch {
	case patternStandaloneA.FindStringIndex(opt) != nil:
		return Arg, next, 2, nil
	case patternStandaloneB.FindStringIndex(opt) != nil:
		return BuildArg, next, 2, nil
	case patternStandaloneI.FindStringIndex(opt) != nil:
		return Include, next, 2, nil
	case patternStandaloneM.FindStringIndex(opt) != nil:
		return SpecifyImage, next, 2, nil
	case patternStandaloneE.FindStringIndex(opt) != nil:
		return Extension, next, 2, nil
	case patternStandaloneC.FindStringIndex(opt) != nil:
		return TargetDir, next, 2, nil
	case patternCombinationA.FindStringIndex(opt) != nil:
		return Arg, patternCombinationA.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationB.FindStringIndex(opt) != nil:
		return BuildArg, patternCombinationB.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationI.FindStringIndex(opt) != nil:
		return Include, patternCombinationI.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationM.FindStringIndex(opt) != nil:
		return SpecifyImage, patternCombinationM.FindStringSubmatch(opt)[1], 1, nil
	case patternCombinationE.FindStringIndex(opt) != nil:
		return SpecifyImage, patternCombinationE.FindStringSubmatch(opt)[1], 1, nil
	case patternUpdateFlag.FindStringIndex(opt) != nil:
		return UpdateFlag, "", 1, nil
	case patternHelpFlag.FindStringIndex(opt) != nil:
		return HelpFlag, "", 1, nil
	case patternVersionFlag.FindStringIndex(opt) != nil:
		return VersionFlag, "", 1, nil
	case patternSource.FindStringIndex(opt) != nil:
		return Source, opt, 1, nil
	default:
		return None, "", 0, fmt.Errorf("Unknown option: %s", opt)
	}
}

// ParseArgs take a string slice comprised of sources, includes, flags, switches
// and their values and returns a map of these types to a string slice
// of the values of each type of option.
func ParseArgs(args []string) map[OptionType][]string {
	if len(args) == 0 {
		return map[OptionType][]string{}
	}

	var next string
	if len(args) > 1 {
		next = args[1]
	}

	optionType, optionValue, nextIndex, _ := ArgToOption(args[0], next)

	if len(args) < nextIndex || nextIndex == 0 {
		return map[OptionType][]string{}
	}

	optionMap := ParseArgs(args[nextIndex:])
	optionMap[optionType] = append([]string{optionValue}, optionMap[optionType]...)
	return optionMap
}

// ParseOsArgs takes a string slice representing the full arguments passed to
// the program, including the filename and returns a CLI containing the
// filename and map of option types to their values.
func ParseOsArgs(args []string) CLI {
	return CLI{
		Filename: args[0],
		Options:  ParseArgs(args[1:]),
	}
}

// DisplayHelp takes a filename and prints the help information for the program.
func DisplayHelp(filename string) {
	fmt.Println("Name:")
	fmt.Printf("\t%s - Execute code in many languages with Docker!\n", filename)
	fmt.Println()
	fmt.Println("Usage:")
	fmt.Printf("\t%s [options]\n", filename)
	fmt.Println()
	fmt.Println("Options:")
	fmt.Printf("\t%-50s%s\n", "<source file>", "Execute source file")
	fmt.Printf("\t%-50s%s\n", "-C <dir>", "Specify source directory")
	fmt.Printf("\t%-50s%s\n", "--arg, -a <argument>", "Pass <argument> to the executing code")
	fmt.Printf("\t%-50s%s\n", "--build-arg, -b <build argument>", "Pass <build argument> to compiler")
	fmt.Printf("\t%-50s%s\n", "--include, -i <file|path>", "Mount local <file|path> in dexec container")
	fmt.Printf("\t%-50s%s\n", "--extension, -e <extension>", "Override the extension used to select image (required for stdin)")
	fmt.Printf("\t%-50s%s\n", "--specify-image, -s <docker image>", "Override the image used with <docker image>")
	fmt.Printf("\t%-50s%s\n", "--update, -u", "Update")
	fmt.Printf("\t%-50s%s\n", "--help, -h", "Show help")
	fmt.Printf("\t%-50s%s\n", "--version, -v", "Display version info")
}

// DisplayVersion prints the version information for the program.
func DisplayVersion(filename string) {
	fmt.Printf("%s 1.0.4-SNAPSHOT\n", filename)
}
<|endoftext|>


<commit_before>// Package cli is a command line interface
package cli

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/micro/cli"
)

var (
	prompt = "\nmicro> "

	commands = map[string]*command{
		"quit":       &command{"quit", "Exit the CLI", quit},
		"exit":       &command{"exit", "Exit the CLI", quit},
		"call":       &command{"call", "Call a service", callService},
		"list":       &command{"list", "List services", listServices},
		"get":        &command{"get", "Get service info", getService},
		"stream":     &command{"stream", "Stream a call to a service", streamService},
		"health":     &command{"health", "Get service health", queryHealth},
		"stats":      &command{"stats", "Get service stats", queryStats},
		"register":   &command{"register", "Register a service", registerService},
		"deregister": &command{"deregister", "Deregister a service", deregisterService},
	}
)

type command struct {
	name  string
	usage string
	exec  func(*cli.Context, []string)
}

func runc(c *cli.Context) {
	commands["help"] = &command{"help", "CLI usage", help}

	scanner := bufio.NewScanner(os.Stdin)

	for {
		// micro>
		fmt.Fprint(os.Stdout, prompt)

		if !scanner.Scan() {
			return
		}

		// get vals
		args := scanner.Text()
		args = strings.TrimSpace(args)

		// skip no args
		if len(args) == 0 {
			continue
		}

		parts := strings.Split(args, " ")
		if len(parts) == 0 {
			continue
		}

		if cmd, ok := commands[parts[0]]; ok {
			cmd.exec(c, parts[1:])
		} else {
			fmt.Fprint(os.Stdout, "unknown command")
		}
	}
}

func registryCommands() []cli.Command {
	return []cli.Command{
		{
			Name:  "list",
			Usage: "List items in registry",
			Subcommands: []cli.Command{
				{
					Name:   "services",
					Usage:  "List services in registry",
					Action: printer(listServices),
				},
			},
		},
		{
			Name:  "register",
			Usage: "Register an item in the registry",
			Subcommands: []cli.Command{
				{
					Name:   "service",
					Usage:  "Register a service with JSON definition",
					Action: printer(registerService),
				},
			},
		},
		{
			Name:  "deregister",
			Usage: "Deregister an item in the registry",
			Subcommands: []cli.Command{
				{
					Name:   "service",
					Usage:  "Deregister a service with JSON definition",
					Action: printer(deregisterService),
				},
			},
		},
		{
			Name:  "get",
			Usage: "Get item from registry",
			Subcommands: []cli.Command{
				{
					Name:   "service",
					Usage:  "Get service from registry",
					Action: printer(getService),
				},
			},
		},
	}
}

func Commands() []cli.Command {
	commands := []cli.Command{
		{
			Name:   "cli",
			Usage:  "Start the interactive cli",
			Action: runc,
		},
		{
			Name:        "registry",
			Usage:       "Query registry",
			Subcommands: registryCommands(),
		},
		{
			Name:   "call",
			Usage:  "Call a service or function",
			Action: printer(callService),
		},
		{
			Name:   "query",
			Usage:  "Deprecated: Use call instead",
			Action: printer(callService),
		},
		{
			Name:   "stream",
			Usage:  "Create a service or function stream",
			Action: printer(streamService),
		},
		{
			Name:   "health",
			Usage:  "Query the health of a service",
			Action: printer(queryHealth),
		},
		{
			Name:   "stats",
			Usage:  "Query the stats of a service",
			Action: printer(queryStats),
		},
	}

	return append(commands, registryCommands()...)
}
<commit_msg>visible query deprecated<commit_after>// Package cli is a command line interface
package cli

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/micro/cli"
)

var (
	prompt = "\nmicro> "

	commands = map[string]*command{
		"quit":       &command{"quit", "Exit the CLI", quit},
		"exit":       &command{"exit", "Exit the CLI", quit},
		"call":       &command{"call", "Call a service", callService},
		"list":       &command{"list", "List services", listServices},
		"get":        &command{"get", "Get service info", getService},
		"stream":     &command{"stream", "Stream a call to a service", streamService},
		"health":     &command{"health", "Get service health", queryHealth},
		"stats":      &command{"stats", "Get service stats", queryStats},
		"register":   &command{"register", "Register a service", registerService},
		"deregister": &command{"deregister", "Deregister a service", deregisterService},
	}
)

type command struct {
	name  string
	usage string
	exec  func(*cli.Context, []string)
}

func runc(c *cli.Context) {
	commands["help"] = &command{"help", "CLI usage", help}

	scanner := bufio.NewScanner(os.Stdin)

	for {
		// micro>
		fmt.Fprint(os.Stdout, prompt)

		if !scanner.Scan() {
			return
		}

		// get vals
		args := scanner.Text()
		args = strings.TrimSpace(args)

		// skip no args
		if len(args) == 0 {
			continue
		}

		parts := strings.Split(args, " ")
		if len(parts) == 0 {
			continue
		}

		if cmd, ok := commands[parts[0]]; ok {
			cmd.exec(c, parts[1:])
		} else {
			fmt.Fprint(os.Stdout, "unknown command")
		}
	}
}

func registryCommands() []cli.Command {
	return []cli.Command{
		{
			Name:  "list",
			Usage: "List items in registry",
			Subcommands: []cli.Command{
				{
					Name:   "services",
					Usage:  "List services in registry",
					Action: printer(listServices),
				},
			},
		},
		{
			Name:  "register",
			Usage: "Register an item in the registry",
			Subcommands: []cli.Command{
				{
					Name:   "service",
					Usage:  "Register a service with JSON definition",
					Action: printer(registerService),
				},
			},
		},
		{
			Name:  "deregister",
			Usage: "Deregister an item in the registry",
			Subcommands: []cli.Command{
				{
					Name:   "service",
					Usage:  "Deregister a service with JSON definition",
					Action: printer(deregisterService),
				},
			},
		},
		{
			Name:  "get",
			Usage: "Get item from registry",
			Subcommands: []cli.Command{
				{
					Name:   "service",
					Usage:  "Get service from registry",
					Action: printer(getService),
				},
			},
		},
	}
}

func Commands() []cli.Command {
	commands := []cli.Command{
		{
			Name:   "cli",
			Usage:  "Start the interactive cli",
			Action: runc,
		},
		{
			Name:        "registry",
			Usage:       "Query registry",
			Subcommands: registryCommands(),
		},
		{
			Name:   "call",
			Usage:  "Call a service or function",
			Action: printer(callService),
		},
		{
			Name:  "query",
			Usage: "Deprecated: Use call instead",
			Action: func(*cli.Context) func(*cli.Context) {
				fmt.Println("Deprecated. Use call instead")
				return printer(callService)
			},
		},
		{
			Name:   "stream",
			Usage:  "Create a service or function stream",
			Action: printer(streamService),
		},
		{
			Name:   "health",
			Usage:  "Query the health of a service",
			Action: printer(queryHealth),
		},
		{
			Name:   "stats",
			Usage:  "Query the stats of a service",
			Action: printer(queryStats),
		},
	}

	return append(commands, registryCommands()...)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"os"
	"regexp"
	"runtime"

	"github.com/gorilla/websocket"
	sm "github.com/ifn/go-statemachine"
)

type DeskMsg struct {
	Desk [][]string `json:"desk"`
}

type PlayerMsg struct {
	Cmd  sm.EventType `json:"command"`
	Card string       `json:"card"`
}

//

var Order map[string]int = map[string]int{
	"6": 6, "7": 7, "8": 8, "9": 9, "10": 10,
	"J": 11,
	"Q": 12,
	"K": 13,
	"A": 14,
}

func higher(c0, c1, t string) int {
	// c0 and c1 have the same suit
	if c0[0] == c1[0] {
		if Order[c0[1:]] > Order[c1[1:]] {
			return 1
		}
		if Order[c0[1:]] < Order[c1[1:]] {
			return -1
		}
		return 0
	}
	// c0 is trump, c1 is not
	if c0[:1] == t {
		return 1
	}
	// c1 is trump, c0 is not
	if c1[:1] == t {
		return -1
	}
	// suits are different, both are not trump
	return -2
}

var CardRE *regexp.Regexp = regexp.MustCompile(`[SCHD]([6-9JQKA]|10)`)

func isValid(c string) bool {
	return CardRE.MatchString(c)
}

//

const (
	cmdStart sm.EventType = iota
	cmdMove

	cmdCount
)

const (
	stateCollection sm.State = iota

	stateAttack
	stateDefense

	stateCount
)

type roundResult bool

const (
	Beat roundResult = true
)

func stateToString(s sm.State) string {
	return [...]string{
		stateCollection: "COLLECTION",
		stateDefense:    "DEFENSE",
		stateAttack:     "ATTACK",
	}[s]
}

func cmdToString(t sm.EventType) string {
	return [...]string{
		cmdStart: "START",
		cmdMove:  "MOVE",
	}[t]
}

//

type cmdArgs struct {
	conn *playerConn
	card string
}

//

type gameState struct {
	// 1. fields that don't change during a game

	sm  *sm.StateMachine
	hub *hub

	// trump suit
	trump string

	// 2. fields that don't change during a round

	// attacker that started a round
	aconnStart *playerConn
	// defender
	dconn *playerConn

	// 3. fields that change during a round

	// attacker
	aconn *playerConn
	// card that should be beaten
	cardToBeat string
}

func (self *gameState) nextPlayer(c *playerConn) *playerConn {
	return self.hub.conns.Next(c)
}

func (self *gameState) finishRound(res roundResult) {
	switch res {
	case Beat:
		self.aconn = self.dconn
	case !Beat:
		self.aconn = self.nextPlayer(self.dconn)
	}
	self.dconn = self.nextPlayer(self.aconn)
}

//

func logOutOfTurn(pconn *playerConn) {
	log.Printf("out of turn: %v", pconn.conn.RemoteAddr())
}

func logWontBeat(c1, c2, t string) {
	log.Printf("%v won't bit %v, trump is ", c1, c2, t)
}

//

func NewGameState() *gameState {
	gst := new(gameState)

	gst.sm = sm.New(stateAttack, uint(stateCount), uint(cmdCount))

	gst.sm.On(cmdMove,
		[]sm.State{stateAttack},
		gst.handleMoveInAttack,
	)
	gst.sm.On(cmdMove,
		[]sm.State{stateDefense},
		gst.handleMoveInDefense,
	)

	gst.sm.On(cmdMove,
		[]sm.State{stateAttack, stateDefense},
		gst.showDesk,
	)

	gst.hub = NewHub()

	return gst
}

// event handlers
// event handlers are actually transition functions.
// in case error event handler should neither change the gameState,
// nor return the state value different from passed to it as an argument.

func (self *gameState) showDesk(s sm.State, e *sm.Event) sm.State {
	log.Println("showDesk")

	return s
}

func (self *gameState) handleMoveInAttack(s sm.State, e *sm.Event) sm.State {
	conn := e.Data.(cmdArgs).conn
	card := e.Data.(cmdArgs).card

	// check that it's conn's turn to move
	if conn != self.aconn {
		logOutOfTurn(conn)
		return s
	}

	// attacker sent the card
	if card != "" {
		self.cardToBeat = card
		return stateDefense
	}

	// attacker sent no card

	aconn := self.nextPlayer(self.aconn)
	if aconn == self.dconn {
		aconn = self.nextPlayer(aconn)
	}

	// check if all attackers have been polled
	if aconn == self.aconnStart {
		self.finishRound(Beat)
		return stateAttack
	}

	self.aconn = aconn
	return stateAttack
}

func (self *gameState) handleMoveInDefense(s sm.State, e *sm.Event) sm.State {
	conn := e.Data.(cmdArgs).conn
	card := e.Data.(cmdArgs).card

	// check that it's conn's turn to move
	if conn != self.dconn {
		logOutOfTurn(conn)
		return s
	}

	// defender takes the cards
	if card == "" {
		self.finishRound(!Beat)
		return stateAttack
	}

	// check that the sent card is capable to beat
	if higher(card, self.cardToBeat, self.trump) != 1 {
		logWontBeat(card, self.cardToBeat, self.trump)
		return s
	}

	return stateAttack
}

//

type playerConn struct {
	gst *gameState

	conn      *websocket.Conn
	hubToConn chan []byte
}

func (self *playerConn) write() {
	defer func() {
		err := self.conn.Close()
		if err != nil {
			log.Println(err)
		}
	}()

	for {
		select {
		case m, ok := <-self.hubToConn:
			if !ok {
				return
			}
			//TODO: text or binary?
			err := self.conn.WriteMessage(websocket.TextMessage, m)
			if err != nil {
				log.Println(err)
				return
			}
		}
	}
}

func (self *playerConn) read() {
	defer func() {
		err := self.conn.Close()
		if err != nil {
			log.Println(err)
		}
	}()

	var m PlayerMsg

	for {
		err := self.conn.ReadJSON(&m)
		if err != nil {
			log.Println(err)
			return
		}

		switch m.Cmd {
		case cmdStart:
			log.Println(cmdToString(cmdStart))
		case cmdMove:
			event := &sm.Event{cmdMove, cmdArgs{self, m.Card}}

			err = self.gst.sm.Emit(event)
			if err != nil {
				log.Println(err)
				return
			}
		}
	}
}

//

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func playerHandler(gst *gameState) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		conn, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			log.Println(err)
			return
		}

		p := &playerConn{gst, conn, make(chan []byte)}

		gst.hub.regChan <- p
		defer func() {
			gst.hub.unregChan <- p
		}()

		go p.write()
		p.read()
	}
}

//

func startDurakSrv() error {
	gst := NewGameState()

	http.HandleFunc("/", playerHandler(gst))

	return http.ListenAndServe(":"+os.Getenv("PORT"), nil)
}

func main() {
	err := startDurakSrv()
	if err != nil {
		log.Fatal(err)
	}
}

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}
<commit_msg>don't look at Origin<commit_after>package main

import (
	"log"
	"net/http"
	"os"
	"regexp"
	"runtime"

	"github.com/gorilla/websocket"
	sm "github.com/ifn/go-statemachine"
)

type DeskMsg struct {
	Desk [][]string `json:"desk"`
}

type PlayerMsg struct {
	Cmd  sm.EventType `json:"command"`
	Card string       `json:"card"`
}

//

var Order map[string]int = map[string]int{
	"6": 6, "7": 7, "8": 8, "9": 9, "10": 10,
	"J": 11,
	"Q": 12,
	"K": 13,
	"A": 14,
}

func higher(c0, c1, t string) int {
	// c0 and c1 have the same suit
	if c0[0] == c1[0] {
		if Order[c0[1:]] > Order[c1[1:]] {
			return 1
		}
		if Order[c0[1:]] < Order[c1[1:]] {
			return -1
		}
		return 0
	}
	// c0 is trump, c1 is not
	if c0[:1] == t {
		return 1
	}
	// c1 is trump, c0 is not
	if c1[:1] == t {
		return -1
	}
	// suits are different, both are not trump
	return -2
}

var CardRE *regexp.Regexp = regexp.MustCompile(`[SCHD]([6-9JQKA]|10)`)

func isValid(c string) bool {
	return CardRE.MatchString(c)
}

//

const (
	cmdStart sm.EventType = iota
	cmdMove

	cmdCount
)

const (
	stateCollection sm.State = iota

	stateAttack
	stateDefense

	stateCount
)

type roundResult bool

const (
	Beat roundResult = true
)

func stateToString(s sm.State) string {
	return [...]string{
		stateCollection: "COLLECTION",
		stateDefense:    "DEFENSE",
		stateAttack:     "ATTACK",
	}[s]
}

func cmdToString(t sm.EventType) string {
	return [...]string{
		cmdStart: "START",
		cmdMove:  "MOVE",
	}[t]
}

//

type cmdArgs struct {
	conn *playerConn
	card string
}

//

type gameState struct {
	// 1. fields that don't change during a game

	sm  *sm.StateMachine
	hub *hub

	// trump suit
	trump string

	// 2. fields that don't change during a round

	// attacker that started a round
	aconnStart *playerConn
	// defender
	dconn *playerConn

	// 3. fields that change during a round

	// attacker
	aconn *playerConn
	// card that should be beaten
	cardToBeat string
}

func (self *gameState) nextPlayer(c *playerConn) *playerConn {
	return self.hub.conns.Next(c)
}

func (self *gameState) finishRound(res roundResult) {
	switch res {
	case Beat:
		self.aconn = self.dconn
	case !Beat:
		self.aconn = self.nextPlayer(self.dconn)
	}
	self.dconn = self.nextPlayer(self.aconn)
}

//

func logOutOfTurn(pconn *playerConn) {
	log.Printf("out of turn: %v", pconn.conn.RemoteAddr())
}

func logWontBeat(c1, c2, t string) {
	log.Printf("%v won't bit %v, trump is ", c1, c2, t)
}

//

func NewGameState() *gameState {
	gst := new(gameState)

	gst.sm = sm.New(stateAttack, uint(stateCount), uint(cmdCount))

	gst.sm.On(cmdMove,
		[]sm.State{stateAttack},
		gst.handleMoveInAttack,
	)
	gst.sm.On(cmdMove,
		[]sm.State{stateDefense},
		gst.handleMoveInDefense,
	)

	gst.sm.On(cmdMove,
		[]sm.State{stateAttack, stateDefense},
		gst.showDesk,
	)

	gst.hub = NewHub()

	return gst
}

// event handlers
// event handlers are actually transition functions.
// in case error event handler should neither change the gameState,
// nor return the state value different from passed to it as an argument.

func (self *gameState) showDesk(s sm.State, e *sm.Event) sm.State {
	log.Println("showDesk")

	return s
}

func (self *gameState) handleMoveInAttack(s sm.State, e *sm.Event) sm.State {
	conn := e.Data.(cmdArgs).conn
	card := e.Data.(cmdArgs).card

	// check that it's conn's turn to move
	if conn != self.aconn {
		logOutOfTurn(conn)
		return s
	}

	// attacker sent the card
	if card != "" {
		self.cardToBeat = card
		return stateDefense
	}

	// attacker sent no card

	aconn := self.nextPlayer(self.aconn)
	if aconn == self.dconn {
		aconn = self.nextPlayer(aconn)
	}

	// check if all attackers have been polled
	if aconn == self.aconnStart {
		self.finishRound(Beat)
		return stateAttack
	}

	self.aconn = aconn
	return stateAttack
}

func (self *gameState) handleMoveInDefense(s sm.State, e *sm.Event) sm.State {
	conn := e.Data.(cmdArgs).conn
	card := e.Data.(cmdArgs).card

	// check that it's conn's turn to move
	if conn != self.dconn {
		logOutOfTurn(conn)
		return s
	}

	// defender takes the cards
	if card == "" {
		self.finishRound(!Beat)
		return stateAttack
	}

	// check that the sent card is capable to beat
	if higher(card, self.cardToBeat, self.trump) != 1 {
		logWontBeat(card, self.cardToBeat, self.trump)
		return s
	}

	return stateAttack
}

//

type playerConn struct {
	gst *gameState

	conn      *websocket.Conn
	hubToConn chan []byte
}

func (self *playerConn) write() {
	defer func() {
		err := self.conn.Close()
		if err != nil {
			log.Println(err)
		}
	}()

	for {
		select {
		case m, ok := <-self.hubToConn:
			if !ok {
				return
			}
			//TODO: text or binary?
			err := self.conn.WriteMessage(websocket.TextMessage, m)
			if err != nil {
				log.Println(err)
				return
			}
		}
	}
}

func (self *playerConn) read() {
	defer func() {
		err := self.conn.Close()
		if err != nil {
			log.Println(err)
		}
	}()

	var m PlayerMsg

	for {
		err := self.conn.ReadJSON(&m)
		if err != nil {
			log.Println(err)
			return
		}

		switch m.Cmd {
		case cmdStart:
			log.Println(cmdToString(cmdStart))
		case cmdMove:
			event := &sm.Event{cmdMove, cmdArgs{self, m.Card}}

			err = self.gst.sm.Emit(event)
			if err != nil {
				log.Println(err)
				return
			}
		}
	}
}

//

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin:     func(r *http.Request) bool { return true },
}

func playerHandler(gst *gameState) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		conn, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			log.Println(err)
			return
		}

		p := &playerConn{gst, conn, make(chan []byte)}

		gst.hub.regChan <- p
		defer func() {
			gst.hub.unregChan <- p
		}()

		go p.write()
		p.read()
	}
}

//

func startDurakSrv() error {
	gst := NewGameState()

	http.HandleFunc("/", playerHandler(gst))

	return http.ListenAndServe(":"+os.Getenv("PORT"), nil)
}

func main() {
	err := startDurakSrv()
	if err != nil {
		log.Fatal(err)
	}
}

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
)

type job struct {
	cmd    string
	stdout chan<- []byte
	stderr chan<- []byte
}

// flag variables
var numWorkers int
var shell string

// global variables
var jobs chan job
var stdouts chan (<-chan []byte)
var stderrs chan (<-chan []byte)
var finish chan bool

func worker() {
	for j := range jobs {
		var stdout, stderr bytes.Buffer
		cmd := exec.Cmd{
			Path:   shell,
			Args:   []string{shell},
			Stdin:  bytes.NewBufferString(j.cmd),
			Stdout: &stdout,
			Stderr: &stderr,
		}
		cmd.Run()
		j.stdout <- stdout.Bytes()
		j.stderr <- stderr.Bytes()
		close(j.stdout)
		close(j.stderr)
	}
}

func inputReader(reader io.Reader) {
	token := make(chan bool, 1)
	token <- true
	bufreader := bufio.NewReader(reader)
	for line, err := bufreader.ReadBytes('\n'); err == nil; line, err = bufreader.ReadBytes('\n') {
		stdout := make(chan []byte)
		stderr := make(chan []byte)
		jobs <- job{cmd: string(line), stdout: stdout, stderr: stderr}
		prev := token
		next := make(chan bool, 1)
		go func() {
			<-prev
			stdouts <- stdout
			stderrs <- stderr
			next <- true
		}()
		token = next
	}
	go func() {
		<-token
		close(stdouts)
		close(stderrs)
	}()
}

func outputWriter(writer io.Writer, chans <-chan (<-chan []byte)) {
	for c := range chans {
		for data := range c {
			writer.Write(data)
		}
	}
	finish <- true
}

func init() {
	flag.IntVar(&numWorkers, "n", -1, "number of workers. -1 means the number of logical CPUs.")
	flag.StringVar(&shell, "shell", "", "Absolute path to your shell.")
}

func main() {
	flag.Parse()
	if numWorkers < 0 {
		if numWorkers != -1 {
			fmt.Fprintln(os.Stderr, "Invalid number of workers.")
			os.Exit(-1)
		}
		numWorkers = runtime.NumCPU()
	}
	if len(shell) == 0 {
		shell = os.Getenv("SHELL")
		if len(shell) == 0 {
			fmt.Fprintln(os.Stderr, "No available shells.")
			os.Exit(-1)
		}
	}
	jobs = make(chan job)
	stdouts = make(chan (<-chan []byte))
	stderrs = make(chan (<-chan []byte))
	finish = make(chan bool, 2)
	go inputReader(os.Stdin)
	go outputWriter(os.Stdout, stdouts)
	go outputWriter(os.Stderr, stderrs)
	for i := 0; i < numWorkers; i += 1 {
		go worker()
	}
	<-finish
	<-finish
}
<commit_msg>fix a concurrency bug<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
)

type job struct {
	cmd    string
	stdout chan<- []byte
	stderr chan<- []byte
}

// flag variables
var numWorkers int
var shell string

// global variables
var jobs chan job
var stdouts chan (<-chan []byte)
var stderrs chan (<-chan []byte)
var finish chan bool

func worker() {
	for j := range jobs {
		var stdout, stderr bytes.Buffer
		cmd := exec.Cmd{
			Path:   shell,
			Args:   []string{shell},
			Stdin:  bytes.NewBufferString(j.cmd),
			Stdout: &stdout,
			Stderr: &stderr,
		}
		cmd.Run()
		go func(j job) {
			j.stdout <- stdout.Bytes()
			j.stderr <- stderr.Bytes()
			close(j.stdout)
			close(j.stderr)
		}(j)
	}
}

func inputReader(reader io.Reader) {
	token := make(chan bool, 1)
	token <- true
	bufreader := bufio.NewReader(reader)
	for line, err := bufreader.ReadBytes('\n'); err == nil; line, err = bufreader.ReadBytes('\n') {
		stdout := make(chan []byte)
		stderr := make(chan []byte)
		jobs <- job{cmd: string(line), stdout: stdout, stderr: stderr}
		prev := token
		next := make(chan bool, 1)
		go func() {
			<-prev
			stdouts <- stdout
			stderrs <- stderr
			next <- true
		}()
		token = next
	}
	go func() {
		<-token
		close(stdouts)
		close(stderrs)
	}()
}

func outputWriter(writer io.Writer, chans <-chan (<-chan []byte)) {
	for c := range chans {
		for data := range c {
			writer.Write(data)
		}
	}
	finish <- true
}

func init() {
	flag.IntVar(&numWorkers, "n", -1, "number of workers. -1 means the number of logical CPUs.")
	flag.StringVar(&shell, "shell", "", "Absolute path to your shell.")
}

func main() {
	flag.Parse()
	if numWorkers < 0 {
		if numWorkers != -1 {
			fmt.Fprintln(os.Stderr, "Invalid number of workers.")
			os.Exit(-1)
		}
		numWorkers = runtime.NumCPU()
	}
	if len(shell) == 0 {
		shell = os.Getenv("SHELL")
		if len(shell) == 0 {
			fmt.Fprintln(os.Stderr, "No available shells.")
			os.Exit(-1)
		}
	}
	jobs = make(chan job)
	stdouts = make(chan (<-chan []byte))
	stderrs = make(chan (<-chan []byte))
	finish = make(chan bool, 2)
	go inputReader(os.Stdin)
	go outputWriter(os.Stdout, stdouts)
	go outputWriter(os.Stderr, stderrs)
	for i := 0; i < numWorkers; i += 1 {
		go worker()
	}
	<-finish
	<-finish
}
<|endoftext|>


<commit_before>package kayvee

import (
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"testing"
)

type Tests struct {
	Version        string     `json:"version"`
	FormatTests    []TestSpec `json:"format"`
	FormatLogTests []TestSpec `json:"formatLog"`
}

type TestSpec struct {
	Title  interface{}            `json:"title"`
	Input  map[string]interface{} `json:"input"`
	Output interface{}            `json:"output"`
}

type keyVal map[string]interface{}

func Test_KayveeSpecs(t *testing.T) {
	file, err := ioutil.ReadFile("tests.json")
	assert.NoError(t, err, "failed to open test specs (tests.json)")
	var tests Tests
	json.Unmarshal(file, &tests)
	t.Logf("spec (tests.json) version: %s\n", string(tests.Version))

	for _, spec := range tests.FormatTests {
		expected := spec.Output
		actual := Format(spec.Input["data"].(map[string]interface{}))
		assert.Equal(t, expected, actual)
	}

	for _, spec := range tests.FormatLogTests {
		expected := spec.Output

		// Ensure correct type is passed to FormatLog, even if value undefined in tests.json
		source, _ := spec.Input["source"].(string)
		level, _ := spec.Input["level"].(string)
		title, _ := spec.Input["title"].(string)
		data, _ := spec.Input["data"].(map[string]interface{})
		actual := FormatLog(source, level, title, data)
		assert.Equal(t, expected, actual)
	}

}
<commit_msg>kayvee_test: Title and Output are always strings<commit_after>package kayvee

import (
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"testing"
)

type Tests struct {
	Version        string     `json:"version"`
	FormatTests    []TestSpec `json:"format"`
	FormatLogTests []TestSpec `json:"formatLog"`
}

type TestSpec struct {
	Title  string                 `json:"title"`
	Input  map[string]interface{} `json:"input"`
	Output string                 `json:"output"`
}

type keyVal map[string]interface{}

func Test_KayveeSpecs(t *testing.T) {
	file, err := ioutil.ReadFile("tests.json")
	assert.NoError(t, err, "failed to open test specs (tests.json)")
	var tests Tests
	json.Unmarshal(file, &tests)
	t.Logf("spec (tests.json) version: %s\n", string(tests.Version))

	for _, spec := range tests.FormatTests {
		expected := spec.Output
		actual := Format(spec.Input["data"].(map[string]interface{}))
		assert.Equal(t, expected, actual)
	}

	for _, spec := range tests.FormatLogTests {
		expected := spec.Output

		// Ensure correct type is passed to FormatLog, even if value undefined in tests.json
		source, _ := spec.Input["source"].(string)
		level, _ := spec.Input["level"].(string)
		title, _ := spec.Input["title"].(string)
		data, _ := spec.Input["data"].(map[string]interface{})
		actual := FormatLog(source, level, title, data)
		assert.Equal(t, expected, actual)
	}

}
<|endoftext|>


<commit_before>package main

import (
  "flag"
  "fmt"
  "os"
  "github.com/lestrrat/go-xslate"
  "github.com/lestrrat/go-xslate/loader"
)

func usage() {
  fmt.Fprintf(os.Stderr, "usage: xslate [options...] [input-files]\n")
  flag.PrintDefaults()
  os.Exit(2)
}

func main() {
  flag.Usage = usage
  flag.Parse()

  args := flag.Args()
  if len(args) < 1 {
    fmt.Fprintf(os.Stderr, "Input file is missing.\n")
    os.Exit(1)
  }

  tx := xslate.New()
  // TODO: Accept --path arguments
  pwd, err := os.Getwd()
  if err != nil {
    fmt.Fprintf(os.Stderr, "Failed to get current working directory: %s\n", err)
    os.Exit(1)
  }
  tx.Loader, _ = loader.NewLoadFile([]string { pwd })
  for _, file := range args {
    output, err := tx.Render(file, nil)
    if err != nil {
      fmt.Fprintf(os.Stderr, "Failed to render %s: %s\n", file, err)
      os.Exit(1)
    }
    fmt.Fprintf(os.Stdout, output)
  }
}<commit_msg>tweak<commit_after>package main

import (
  "flag"
  "fmt"
  "os"
  "github.com/lestrrat/go-xslate"
  "github.com/lestrrat/go-xslate/loader"
)

func usage() {
  fmt.Fprintf(os.Stderr, "usage: xslate [options...] [input-files]\n")
  flag.PrintDefaults()
  os.Exit(2)
}

func main() {
  flag.Usage = usage
  flag.Parse()

  args := flag.Args()
  if len(args) < 1 {
    fmt.Fprintf(os.Stderr, "Input file is missing.\n")
    os.Exit(1)
  }

  tx := xslate.New()
  // TODO: Accept --path arguments
  pwd, err := os.Getwd()
  if err != nil {
    fmt.Fprintf(os.Stderr, "Failed to get current working directory: %s\n", err)
    os.Exit(1)
  }
  tx.Loader, _ = loader.DefaultLoader(
    os.TempDir(),
    []string { pwd },
    tx.Parser,
    tx.Compiler,
  )
  for _, file := range args {
    output, err := tx.Render(file, nil)
    if err != nil {
      fmt.Fprintf(os.Stderr, "Failed to render %s: %s\n", file, err)
      os.Exit(1)
    }
    fmt.Fprintf(os.Stdout, output)
  }
}<|endoftext|>


<commit_before>package clicommand

import (
	"errors"
	"fmt"
	"os"
	"reflect"
	"strings"

	"github.com/buildkite/agent/v3/agent"
	"github.com/buildkite/agent/v3/api"
	"github.com/buildkite/agent/v3/experiments"
	"github.com/buildkite/agent/v3/logger"
	"github.com/oleiade/reflections"
	"github.com/urfave/cli"
)

const (
	DefaultEndpoint = "https://agent.buildkite.com/v3"
)

var AgentAccessTokenFlag = cli.StringFlag{
	Name:   "agent-access-token",
	Value:  "",
	Usage:  "The access token used to identify the agent",
	EnvVar: "BUILDKITE_AGENT_ACCESS_TOKEN",
}

var AgentRegisterTokenFlag = cli.StringFlag{
	Name:   "token",
	Value:  "",
	Usage:  "Your account agent token",
	EnvVar: "BUILDKITE_AGENT_TOKEN",
}

var EndpointFlag = cli.StringFlag{
	Name:   "endpoint",
	Value:  DefaultEndpoint,
	Usage:  "The Agent API endpoint",
	EnvVar: "BUILDKITE_AGENT_ENDPOINT",
}

var NoHTTP2Flag = cli.BoolFlag{
	Name:   "no-http2",
	Usage:  "Disable HTTP2 when communicating with the Agent API.",
	EnvVar: "BUILDKITE_NO_HTTP2",
}

var DebugFlag = cli.BoolFlag{
	Name:   "debug",
	Usage:  "Enable debug mode. Synonym for ′--log-level debug′. Takes precedence over ′--log-level′",
	EnvVar: "BUILDKITE_AGENT_DEBUG",
}

var LogLevelFlag = cli.StringFlag{
	Name:   "log-level",
	Value:  "notice",
	Usage:  "Set the log level for the agent, making logging more or less verbose. Defaults to notice",
	EnvVar: "BUILDKITE_AGENT_LOG_LEVEL",
}

var ProfileFlag = cli.StringFlag{
	Name:   "profile",
	Usage:  "Enable a profiling mode, either cpu, memory, mutex or block",
	EnvVar: "BUILDKITE_AGENT_PROFILE",
}

var DebugHTTPFlag = cli.BoolFlag{
	Name:   "debug-http",
	Usage:  "Enable HTTP debug mode, which dumps all request and response bodies to the log",
	EnvVar: "BUILDKITE_AGENT_DEBUG_HTTP",
}

var NoColorFlag = cli.BoolFlag{
	Name:   "no-color",
	Usage:  "Don't show colors in logging",
	EnvVar: "BUILDKITE_AGENT_NO_COLOR",
}

var ExperimentsFlag = cli.StringSliceFlag{
	Name:   "experiment",
	Value:  &cli.StringSlice{},
	Usage:  "Enable experimental features within the buildkite-agent",
	EnvVar: "BUILDKITE_AGENT_EXPERIMENT",
}

var RedactedVars = cli.StringSliceFlag{
	Name:   "redacted-vars",
	Usage:  "Pattern of environment variable names containing sensitive values",
	EnvVar: "BUILDKITE_REDACTED_VARS",
	Value:  &cli.StringSlice{"*_PASSWORD", "*_SECRET", "*_TOKEN", "*_ACCESS_KEY", "*_SECRET_KEY"},
}

func CreateLogger(cfg interface{}) logger.Logger {
	var l logger.Logger
	logFormat := `text`

	// Check the LogFormat config field
	if logFormatCfg, err := reflections.GetField(cfg, "LogFormat"); err == nil {
		if logFormatString, ok := logFormatCfg.(string); ok {
			logFormat = logFormatString
		}
	}

	// Create a logger based on the type
	switch logFormat {
	case `text`, ``:
		printer := logger.NewTextPrinter(os.Stderr)

		// Show agent fields as a prefix
		printer.IsPrefixFn = func(field logger.Field) bool {
			switch field.Key() {
			case "agent", "hook":
				return true
			default:
				return false
			}
		}

		// Turn off color if a NoColor option is present
		noColor, err := reflections.GetField(cfg, "NoColor")
		if noColor == true && err == nil {
			printer.Colors = false
		} else {
			printer.Colors = true
		}

		l = logger.NewConsoleLogger(printer, os.Exit)
	case `json`:
		l.Warn("FORMAT IS JSON")
		l = logger.NewConsoleLogger(logger.NewJSONPrinter(os.Stdout), os.Exit)
	default:
		fmt.Printf("Unknown log-format of %q, try text or json\n", logFormat)
		os.Exit(1)
	}

	l.SetLevel(logger.NOTICE)

	err := handleLogLevelFlag(l, cfg)
	if err != nil {
		l.Warn("Error when setting log level: %v. Defaulting log level to NOTICE", err)
	}

	// Enable debugging if a Debug option is present
	debugI, _ := reflections.GetField(cfg, "Debug")
	if debug, ok := debugI.(bool); ok && debug {
		l.SetLevel(logger.DEBUG)
	}

	return l
}

func HandleProfileFlag(l logger.Logger, cfg interface{}) func() {
	// Enable profiling a profiling mode if Profile is present
	modeField, _ := reflections.GetField(cfg, "Profile")
	if mode, ok := modeField.(string); ok && mode != "" {
		return Profile(l, mode)
	}
	return func() {}
}

func HandleGlobalFlags(l logger.Logger, cfg interface{}) func() {
	// Enable experiments
	experimentNames, err := reflections.GetField(cfg, "Experiments")
	if err == nil {
		experimentNamesSlice, ok := experimentNames.([]string)
		if ok {
			for _, name := range experimentNamesSlice {
				experiments.Enable(name)
				l.Debug("Enabled experiment `%s`", name)
			}
		}
	}

	// Handle profiling flag
	return HandleProfileFlag(l, cfg)
}

func handleLogLevelFlag(l logger.Logger, cfg interface{}) error {
	logLevel, err := reflections.GetField(cfg, "LogLevel")
	if err != nil {
		return err
	}

	llStr, ok := logLevel.(string)
	if !ok {
		return fmt.Errorf("log level %v (%T) couldn't be cast to string", logLevel, logLevel)
	}

	level, err := logger.LevelFromString(llStr)
	if err != nil {
		return err
	}

	l.SetLevel(level)
	return nil
}

func UnsetConfigFromEnvironment(c *cli.Context) error {
	flags := append(c.App.Flags, c.Command.Flags...)
	for _, fl := range flags {
		// use golang reflection to find EnvVar values on flags
		r := reflect.ValueOf(fl)
		f := reflect.Indirect(r).FieldByName(`EnvVar`)
		if !f.IsValid() {
			return errors.New("EnvVar field not found on flag")
		}
		// split comma delimited env
		if envVars := f.String(); envVars != `` {
			for _, env := range strings.Split(envVars, ",") {
				os.Unsetenv(env)
			}
		}
	}
	return nil
}

func loadAPIClientConfig(cfg interface{}, tokenField string) api.Config {
	conf := api.Config{
		UserAgent: agent.UserAgent(),
	}

	// Enable HTTP debugging
	debugHTTP, err := reflections.GetField(cfg, "DebugHTTP")
	if debugHTTP == true && err == nil {
		conf.DebugHTTP = true
	}

	endpoint, err := reflections.GetField(cfg, "Endpoint")
	if endpoint != "" && err == nil {
		conf.Endpoint = endpoint.(string)
	}

	token, err := reflections.GetField(cfg, tokenField)
	if token != "" && err == nil {
		conf.Token = token.(string)
	}

	noHTTP2, err := reflections.GetField(cfg, "NoHTTP2")
	if err == nil {
		conf.DisableHTTP2 = noHTTP2.(bool)
	}

	return conf
}
<commit_msg>Fix nil pointer deref when using --log-format json<commit_after>package clicommand

import (
	"errors"
	"fmt"
	"os"
	"reflect"
	"strings"

	"github.com/buildkite/agent/v3/agent"
	"github.com/buildkite/agent/v3/api"
	"github.com/buildkite/agent/v3/experiments"
	"github.com/buildkite/agent/v3/logger"
	"github.com/oleiade/reflections"
	"github.com/urfave/cli"
)

const (
	DefaultEndpoint = "https://agent.buildkite.com/v3"
)

var AgentAccessTokenFlag = cli.StringFlag{
	Name:   "agent-access-token",
	Value:  "",
	Usage:  "The access token used to identify the agent",
	EnvVar: "BUILDKITE_AGENT_ACCESS_TOKEN",
}

var AgentRegisterTokenFlag = cli.StringFlag{
	Name:   "token",
	Value:  "",
	Usage:  "Your account agent token",
	EnvVar: "BUILDKITE_AGENT_TOKEN",
}

var EndpointFlag = cli.StringFlag{
	Name:   "endpoint",
	Value:  DefaultEndpoint,
	Usage:  "The Agent API endpoint",
	EnvVar: "BUILDKITE_AGENT_ENDPOINT",
}

var NoHTTP2Flag = cli.BoolFlag{
	Name:   "no-http2",
	Usage:  "Disable HTTP2 when communicating with the Agent API.",
	EnvVar: "BUILDKITE_NO_HTTP2",
}

var DebugFlag = cli.BoolFlag{
	Name:   "debug",
	Usage:  "Enable debug mode. Synonym for ′--log-level debug′. Takes precedence over ′--log-level′",
	EnvVar: "BUILDKITE_AGENT_DEBUG",
}

var LogLevelFlag = cli.StringFlag{
	Name:   "log-level",
	Value:  "notice",
	Usage:  "Set the log level for the agent, making logging more or less verbose. Defaults to notice",
	EnvVar: "BUILDKITE_AGENT_LOG_LEVEL",
}

var ProfileFlag = cli.StringFlag{
	Name:   "profile",
	Usage:  "Enable a profiling mode, either cpu, memory, mutex or block",
	EnvVar: "BUILDKITE_AGENT_PROFILE",
}

var DebugHTTPFlag = cli.BoolFlag{
	Name:   "debug-http",
	Usage:  "Enable HTTP debug mode, which dumps all request and response bodies to the log",
	EnvVar: "BUILDKITE_AGENT_DEBUG_HTTP",
}

var NoColorFlag = cli.BoolFlag{
	Name:   "no-color",
	Usage:  "Don't show colors in logging",
	EnvVar: "BUILDKITE_AGENT_NO_COLOR",
}

var ExperimentsFlag = cli.StringSliceFlag{
	Name:   "experiment",
	Value:  &cli.StringSlice{},
	Usage:  "Enable experimental features within the buildkite-agent",
	EnvVar: "BUILDKITE_AGENT_EXPERIMENT",
}

var RedactedVars = cli.StringSliceFlag{
	Name:   "redacted-vars",
	Usage:  "Pattern of environment variable names containing sensitive values",
	EnvVar: "BUILDKITE_REDACTED_VARS",
	Value:  &cli.StringSlice{"*_PASSWORD", "*_SECRET", "*_TOKEN", "*_ACCESS_KEY", "*_SECRET_KEY"},
}

func CreateLogger(cfg interface{}) logger.Logger {
	var l logger.Logger
	logFormat := `text`

	// Check the LogFormat config field
	if logFormatCfg, err := reflections.GetField(cfg, "LogFormat"); err == nil {
		if logFormatString, ok := logFormatCfg.(string); ok {
			logFormat = logFormatString
		}
	}

	// Create a logger based on the type
	switch logFormat {
	case `text`, ``:
		printer := logger.NewTextPrinter(os.Stderr)

		// Show agent fields as a prefix
		printer.IsPrefixFn = func(field logger.Field) bool {
			switch field.Key() {
			case "agent", "hook":
				return true
			default:
				return false
			}
		}

		// Turn off color if a NoColor option is present
		noColor, err := reflections.GetField(cfg, "NoColor")
		if noColor == true && err == nil {
			printer.Colors = false
		} else {
			printer.Colors = true
		}

		l = logger.NewConsoleLogger(printer, os.Exit)
	case `json`:
		l = logger.NewConsoleLogger(logger.NewJSONPrinter(os.Stdout), os.Exit)
	default:
		fmt.Printf("Unknown log-format of %q, try text or json\n", logFormat)
		os.Exit(1)
	}

	l.SetLevel(logger.NOTICE)

	err := handleLogLevelFlag(l, cfg)
	if err != nil {
		l.Warn("Error when setting log level: %v. Defaulting log level to NOTICE", err)
	}

	// Enable debugging if a Debug option is present
	debugI, _ := reflections.GetField(cfg, "Debug")
	if debug, ok := debugI.(bool); ok && debug {
		l.SetLevel(logger.DEBUG)
	}

	return l
}

func HandleProfileFlag(l logger.Logger, cfg interface{}) func() {
	// Enable profiling a profiling mode if Profile is present
	modeField, _ := reflections.GetField(cfg, "Profile")
	if mode, ok := modeField.(string); ok && mode != "" {
		return Profile(l, mode)
	}
	return func() {}
}

func HandleGlobalFlags(l logger.Logger, cfg interface{}) func() {
	// Enable experiments
	experimentNames, err := reflections.GetField(cfg, "Experiments")
	if err == nil {
		experimentNamesSlice, ok := experimentNames.([]string)
		if ok {
			for _, name := range experimentNamesSlice {
				experiments.Enable(name)
				l.Debug("Enabled experiment `%s`", name)
			}
		}
	}

	// Handle profiling flag
	return HandleProfileFlag(l, cfg)
}

func handleLogLevelFlag(l logger.Logger, cfg interface{}) error {
	logLevel, err := reflections.GetField(cfg, "LogLevel")
	if err != nil {
		return err
	}

	llStr, ok := logLevel.(string)
	if !ok {
		return fmt.Errorf("log level %v (%T) couldn't be cast to string", logLevel, logLevel)
	}

	level, err := logger.LevelFromString(llStr)
	if err != nil {
		return err
	}

	l.SetLevel(level)
	return nil
}

func UnsetConfigFromEnvironment(c *cli.Context) error {
	flags := append(c.App.Flags, c.Command.Flags...)
	for _, fl := range flags {
		// use golang reflection to find EnvVar values on flags
		r := reflect.ValueOf(fl)
		f := reflect.Indirect(r).FieldByName(`EnvVar`)
		if !f.IsValid() {
			return errors.New("EnvVar field not found on flag")
		}
		// split comma delimited env
		if envVars := f.String(); envVars != `` {
			for _, env := range strings.Split(envVars, ",") {
				os.Unsetenv(env)
			}
		}
	}
	return nil
}

func loadAPIClientConfig(cfg interface{}, tokenField string) api.Config {
	conf := api.Config{
		UserAgent: agent.UserAgent(),
	}

	// Enable HTTP debugging
	debugHTTP, err := reflections.GetField(cfg, "DebugHTTP")
	if debugHTTP == true && err == nil {
		conf.DebugHTTP = true
	}

	endpoint, err := reflections.GetField(cfg, "Endpoint")
	if endpoint != "" && err == nil {
		conf.Endpoint = endpoint.(string)
	}

	token, err := reflections.GetField(cfg, tokenField)
	if token != "" && err == nil {
		conf.Token = token.(string)
	}

	noHTTP2, err := reflections.GetField(cfg, "NoHTTP2")
	if err == nil {
		conf.DisableHTTP2 = noHTTP2.(bool)
	}

	return conf
}
<|endoftext|>


<commit_before>package client

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"sync"
	"time"

	"github.com/myodc/go-micro/broker"
	c "github.com/myodc/go-micro/context"
	"github.com/myodc/go-micro/errors"
	"github.com/myodc/go-micro/registry"
	"github.com/myodc/go-micro/transport"

	rpc "github.com/youtube/vitess/go/rpcplus"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"
)

type headerRoundTripper struct {
	r http.RoundTripper
}

type rpcClient struct {
	once sync.Once
	opts options
}

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

func newRpcClient(opt ...Option) Client {
	var opts options

	for _, o := range opt {
		o(&opts)
	}

	if opts.transport == nil {
		opts.transport = transport.DefaultTransport
	}

	if opts.broker == nil {
		opts.broker = broker.DefaultBroker
	}

	var once sync.Once

	return &rpcClient{
		once: once,
		opts: opts,
	}
}

func (t *headerRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	r.Header.Set("X-Client-Version", "1.0")
	return t.r.RoundTrip(r)
}

func (r *rpcClient) call(ctx context.Context, address string, request Request, response interface{}) error {
	msg := &transport.Message{
		Header: make(map[string]string),
	}

	md, ok := c.GetMetadata(ctx)
	if ok {
		for k, v := range md {
			msg.Header[k] = v
		}
	}

	msg.Header["Content-Type"] = request.ContentType()

	c, err := r.opts.transport.Dial(address)
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err))
	}

	client := rpc.NewClientWithCodec(newRpcPlusCodec(msg, c))
	return client.Call(ctx, request.Method(), request.Request(), response)
}

func (r *rpcClient) stream(ctx context.Context, address string, request Request, responseChan interface{}) (Streamer, error) {
	msg := &transport.Message{
		Header: make(map[string]string),
	}

	md, ok := c.GetMetadata(ctx)
	if ok {
		for k, v := range md {
			msg.Header[k] = v
		}
	}

	msg.Header["Content-Type"] = request.ContentType()

	c, err := r.opts.transport.Dial(address, transport.WithStream())
	if err != nil {
		return nil, errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err))
	}

	client := rpc.NewClientWithCodec(newRpcPlusCodec(msg, c))
	call := client.StreamGo(request.Method(), request.Request(), responseChan)

	return &rpcStream{
		request: request,
		call:    call,
		client:  client,
	}, nil
}

func (r *rpcClient) CallRemote(ctx context.Context, address string, request Request, response interface{}) error {
	return r.call(ctx, address, request, response)
}

// TODO: Call(..., opts *Options) error {
func (r *rpcClient) Call(ctx context.Context, request Request, response interface{}) error {
	service, err := registry.GetService(request.Service())
	if err != nil {
		return errors.InternalServerError("go.micro.client", err.Error())
	}

	if len(service.Nodes) == 0 {
		return errors.NotFound("go.micro.client", "Service not found")
	}

	n := rand.Int() % len(service.Nodes)
	node := service.Nodes[n]

	address := node.Address
	if node.Port > 0 {
		address = fmt.Sprintf("%s:%d", address, node.Port)
	}

	return r.call(ctx, address, request, response)
}

func (r *rpcClient) StreamRemote(ctx context.Context, address string, request Request, responseChan interface{}) (Streamer, error) {
	return r.stream(ctx, address, request, responseChan)
}

func (r *rpcClient) Stream(ctx context.Context, request Request, responseChan interface{}) (Streamer, error) {
	service, err := registry.GetService(request.Service())
	if err != nil {
		return nil, errors.InternalServerError("go.micro.client", err.Error())
	}

	if len(service.Nodes) == 0 {
		return nil, errors.NotFound("go.micro.client", "Service not found")
	}

	n := rand.Int() % len(service.Nodes)
	node := service.Nodes[n]

	address := node.Address
	if node.Port > 0 {
		address = fmt.Sprintf("%s:%d", address, node.Port)
	}

	return r.stream(ctx, address, request, responseChan)
}

func (r *rpcClient) Publish(ctx context.Context, p Publication) error {
	md, ok := c.GetMetadata(ctx)
	if !ok {
		md = make(map[string]string)
	}
	md["Content-Type"] = p.ContentType()

	// encode message body
	var body []byte

	switch p.ContentType() {
	case "application/octet-stream":
		b, err := proto.Marshal(p.Message().(proto.Message))
		if err != nil {
			return err
		}
		body = b
	case "application/json":
		b, err := json.Marshal(p.Message())
		if err != nil {
			return err
		}
		body = b
	}

	r.once.Do(func() {
		r.opts.broker.Connect()
	})

	return r.opts.broker.Publish(p.Topic(), &broker.Message{
		Header: md,
		Body:   body,
	})
}

func (r *rpcClient) NewPublication(topic string, message interface{}) Publication {
	return r.NewProtoPublication(topic, message)
}

func (r *rpcClient) NewProtoPublication(topic string, message interface{}) Publication {
	return newRpcPublication(topic, message, "application/octet-stream")
}
func (r *rpcClient) NewRequest(service, method string, request interface{}) Request {
	return r.NewProtoRequest(service, method, request)
}

func (r *rpcClient) NewProtoRequest(service, method string, request interface{}) Request {
	return newRpcRequest(service, method, request, "application/octet-stream")
}

func (r *rpcClient) NewJsonRequest(service, method string, request interface{}) Request {
	return newRpcRequest(service, method, request, "application/json")
}
<commit_msg>Fix connection leak<commit_after>package client

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"net/http"
	"sync"
	"time"

	"github.com/myodc/go-micro/broker"
	c "github.com/myodc/go-micro/context"
	"github.com/myodc/go-micro/errors"
	"github.com/myodc/go-micro/registry"
	"github.com/myodc/go-micro/transport"

	rpc "github.com/youtube/vitess/go/rpcplus"

	"github.com/golang/protobuf/proto"
	"golang.org/x/net/context"
)

type headerRoundTripper struct {
	r http.RoundTripper
}

type rpcClient struct {
	once sync.Once
	opts options
}

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

func newRpcClient(opt ...Option) Client {
	var opts options

	for _, o := range opt {
		o(&opts)
	}

	if opts.transport == nil {
		opts.transport = transport.DefaultTransport
	}

	if opts.broker == nil {
		opts.broker = broker.DefaultBroker
	}

	var once sync.Once

	return &rpcClient{
		once: once,
		opts: opts,
	}
}

func (t *headerRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
	r.Header.Set("X-Client-Version", "1.0")
	return t.r.RoundTrip(r)
}

func (r *rpcClient) call(ctx context.Context, address string, request Request, response interface{}) error {
	msg := &transport.Message{
		Header: make(map[string]string),
	}

	md, ok := c.GetMetadata(ctx)
	if ok {
		for k, v := range md {
			msg.Header[k] = v
		}
	}

	msg.Header["Content-Type"] = request.ContentType()

	c, err := r.opts.transport.Dial(address)
	if err != nil {
		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err))
	}
	defer c.Close()

	client := rpc.NewClientWithCodec(newRpcPlusCodec(msg, c))
	return client.Call(ctx, request.Method(), request.Request(), response)
}

func (r *rpcClient) stream(ctx context.Context, address string, request Request, responseChan interface{}) (Streamer, error) {
	msg := &transport.Message{
		Header: make(map[string]string),
	}

	md, ok := c.GetMetadata(ctx)
	if ok {
		for k, v := range md {
			msg.Header[k] = v
		}
	}

	msg.Header["Content-Type"] = request.ContentType()

	c, err := r.opts.transport.Dial(address, transport.WithStream())
	if err != nil {
		return nil, errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err))
	}

	client := rpc.NewClientWithCodec(newRpcPlusCodec(msg, c))
	call := client.StreamGo(request.Method(), request.Request(), responseChan)

	return &rpcStream{
		request: request,
		call:    call,
		client:  client,
	}, nil
}

func (r *rpcClient) CallRemote(ctx context.Context, address string, request Request, response interface{}) error {
	return r.call(ctx, address, request, response)
}

// TODO: Call(..., opts *Options) error {
func (r *rpcClient) Call(ctx context.Context, request Request, response interface{}) error {
	service, err := registry.GetService(request.Service())
	if err != nil {
		return errors.InternalServerError("go.micro.client", err.Error())
	}

	if len(service.Nodes) == 0 {
		return errors.NotFound("go.micro.client", "Service not found")
	}

	n := rand.Int() % len(service.Nodes)
	node := service.Nodes[n]

	address := node.Address
	if node.Port > 0 {
		address = fmt.Sprintf("%s:%d", address, node.Port)
	}

	return r.call(ctx, address, request, response)
}

func (r *rpcClient) StreamRemote(ctx context.Context, address string, request Request, responseChan interface{}) (Streamer, error) {
	return r.stream(ctx, address, request, responseChan)
}

func (r *rpcClient) Stream(ctx context.Context, request Request, responseChan interface{}) (Streamer, error) {
	service, err := registry.GetService(request.Service())
	if err != nil {
		return nil, errors.InternalServerError("go.micro.client", err.Error())
	}

	if len(service.Nodes) == 0 {
		return nil, errors.NotFound("go.micro.client", "Service not found")
	}

	n := rand.Int() % len(service.Nodes)
	node := service.Nodes[n]

	address := node.Address
	if node.Port > 0 {
		address = fmt.Sprintf("%s:%d", address, node.Port)
	}

	return r.stream(ctx, address, request, responseChan)
}

func (r *rpcClient) Publish(ctx context.Context, p Publication) error {
	md, ok := c.GetMetadata(ctx)
	if !ok {
		md = make(map[string]string)
	}
	md["Content-Type"] = p.ContentType()

	// encode message body
	var body []byte

	switch p.ContentType() {
	case "application/octet-stream":
		b, err := proto.Marshal(p.Message().(proto.Message))
		if err != nil {
			return err
		}
		body = b
	case "application/json":
		b, err := json.Marshal(p.Message())
		if err != nil {
			return err
		}
		body = b
	}

	r.once.Do(func() {
		r.opts.broker.Connect()
	})

	return r.opts.broker.Publish(p.Topic(), &broker.Message{
		Header: md,
		Body:   body,
	})
}

func (r *rpcClient) NewPublication(topic string, message interface{}) Publication {
	return r.NewProtoPublication(topic, message)
}

func (r *rpcClient) NewProtoPublication(topic string, message interface{}) Publication {
	return newRpcPublication(topic, message, "application/octet-stream")
}
func (r *rpcClient) NewRequest(service, method string, request interface{}) Request {
	return r.NewProtoRequest(service, method, request)
}

func (r *rpcClient) NewProtoRequest(service, method string, request interface{}) Request {
	return newRpcRequest(service, method, request, "application/octet-stream")
}

func (r *rpcClient) NewJsonRequest(service, method string, request interface{}) Request {
	return newRpcRequest(service, method, request, "application/json")
}
<|endoftext|>


<commit_before>// Copyright 2013-present Greg Hurrell. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"os/user"
	"path/filepath"
	"strings"
	"syscall"
)

type Options struct {
	Address string
	Config  string
	Logfile string
	Port    int
}

var config Options // Options read from disk.
var flags Options  // Options set via commandline flags.
var defaults = Options{
	Address: "127.0.0.1",
	Config:  "~/.clipper.json",
	Logfile: "~/Library/Logs/com.wincent.clipper.log",
	Port:    8377,
}

const (
	pbcopy = "pbcopy"
)

func init() {
	const (
		listenAddrUsage = "address to bind to"
		listenPortUsage = "port to listen on"
		logFileUsage    = "path to logfile"
		configFileUsage = "path to (JSON) config file"
		shorthand       = " (shorthand)"
	)

	flag.StringVar(&flags.Address, "address", defaults.Address, listenAddrUsage)
	flag.StringVar(&flags.Address, "a", defaults.Address, listenAddrUsage+shorthand)
	flag.IntVar(&flags.Port, "port", defaults.Port, listenPortUsage)
	flag.IntVar(&flags.Port, "p", defaults.Port, listenPortUsage+shorthand)
	flag.StringVar(&flags.Logfile, "logfile", defaults.Logfile, logFileUsage)
	flag.StringVar(&flags.Logfile, "l", defaults.Logfile, logFileUsage)
	flag.StringVar(&flags.Config, "config", defaults.Config, configFileUsage)
	flag.StringVar(&flags.Config, "c", defaults.Config, configFileUsage+shorthand)
}

func main() {
	flag.Parse()
	if flag.NArg() != 0 {
		// additional command-line options not supported
		flag.Usage()
		os.Exit(1)
	}

	expandedPath := expandPath(flags.Logfile)
	outfile, err := os.OpenFile(expandedPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		log.Fatal(err)
	}
	defer outfile.Close()
	log.SetOutput(outfile)
	log.SetPrefix("clipper: ")

	if _, err := exec.LookPath(pbcopy); err != nil {
		log.Fatal(err)
	}

	expandedPath = expandPath(flags.Config)
	if configData, err := ioutil.ReadFile(expandedPath); err != nil {
		if flags.Config == defaults.Config {
			// default config file missing; just warn
			log.Print(err)
		} else {
			// user explicitly asked for non-default config file; fail hard
			log.Fatal(err)
		}
	} else {
		if err = json.Unmarshal(configData, &config); err != nil {
			log.Fatal(err)
		}
	}

	var addr string
	var listenType string
	if isPath(config.Address) {
		addr = expandPath(config.Address)
	} else if isPath(flags.Address) {
		addr = expandPath(flags.Address)
	} else {
		addr = flags.Address
	}
	if strings.HasPrefix(addr, "/") {
		log.Print("Starting UNIX domain socket server at ", addr)
		listenType = "unix"
	} else {
		log.Print("Starting TCP server on ", addr)
		listenType = "tcp"
		addr = fmt.Sprintf("%s:%d", flags.Address, flags.Port)
	}
	listener, err := net.Listen(listenType, addr)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				log.Print(err)
				return
			}

			go handleConnection(conn)
		}
	}()

	// Need to catch signals in order for `defer`-ed clean-up items to run.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM)
	sig := <-c
	log.Print("Got signal ", sig)
}

// Returns true for things which look like paths (start with "~", "." or "/").
func isPath(path string) bool {
	return strings.HasPrefix(path, "~") ||
		strings.HasPrefix(path, ".") ||
		strings.HasPrefix(path, "/")
}

func expandPath(path string) string {
	expanded := pathByExpandingTildeInPath(path)
	result, err := filepath.Abs(expanded)
	if err != nil {
		log.Fatal(err)
	}
	return result
}

func pathByExpandingTildeInPath(path string) string {
	if strings.HasPrefix(path, "~") {
		user, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		path = user.HomeDir + path[1:]
	}
	return path
}

func handleConnection(conn net.Conn) {
	defer log.Print("Connection closed")
	defer conn.Close()

	cmd := exec.Command(pbcopy)
	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Print(err)
		return
	}
	if err = cmd.Start(); err != nil {
		log.Print(err)
		return
	}

	if copied, err := io.Copy(stdin, conn); err != nil {
		log.Print(err)
	} else {
		log.Print("Echoed ", copied, " bytes")
	}
	stdin.Close()

	if err = cmd.Wait(); err != nil {
		log.Print(err)
	}
}
<commit_msg>Rejig settings handling to get desired precedence<commit_after>// Copyright 2013-present Greg Hurrell. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"os/user"
	"path/filepath"
	"strings"
	"syscall"
)

type Options struct {
	Address string
	Config  string
	Logfile string
	Port    int
}

var config Options // Options read from disk.
var flags Options  // Options set via commandline flags.
var defaults = Options{
	Address: "127.0.0.1",
	Config:  "~/.clipper.json",
	Logfile: "~/Library/Logs/com.wincent.clipper.log",
	Port:    8377,
}
var settings Options // Result of merging: flags > config > defaults.

const (
	pbcopy = "pbcopy"
)

func init() {
	const (
		listenAddrUsage = "address to bind to"
		listenPortUsage = "port to listen on"
		logFileUsage    = "path to logfile"
		configFileUsage = "path to (JSON) config file"
		shorthand       = " (shorthand)"
	)

	flag.StringVar(&flags.Address, "address", defaults.Address, listenAddrUsage)
	flag.StringVar(&flags.Address, "a", defaults.Address, listenAddrUsage+shorthand)
	flag.IntVar(&flags.Port, "port", defaults.Port, listenPortUsage)
	flag.IntVar(&flags.Port, "p", defaults.Port, listenPortUsage+shorthand)
	flag.StringVar(&flags.Logfile, "logfile", defaults.Logfile, logFileUsage)
	flag.StringVar(&flags.Logfile, "l", defaults.Logfile, logFileUsage)
	flag.StringVar(&flags.Config, "config", defaults.Config, configFileUsage)
	flag.StringVar(&flags.Config, "c", defaults.Config, configFileUsage+shorthand)
}

func main() {
	// Set this up before we even know where our logfile is, in case we have to
	// bail early and print something to stderr.
	log.SetPrefix("clipper: ")

	flag.Parse()
	if flag.NArg() != 0 {
		// Additional command-line options not supported.
		flag.Usage()
		os.Exit(1)
	}

	// Detect which flags were passed in explicitly, and set them immediately.
	// This is used below to determine response to a missing config file.
	visitor := func(f *flag.Flag) {
		if f.Name == "address" || f.Name == "a" {
			settings.Address = flags.Address
		} else if f.Name == "config" || f.Name == "c" {
			settings.Config = flags.Config
		} else if f.Name == "port" || f.Name == "p" {
			settings.Port = flags.Port
		} else if f.Name == "logfile" || f.Name == "l" {
			settings.Logfile = flags.Logfile
		}
	}
	flag.Visit(visitor)

	expandedPath := expandPath(flags.Config)
	if configData, err := ioutil.ReadFile(expandedPath); err != nil {
		if settings.Config != "" {
			// User explicitly asked for a config file and it wasn't there; fail
			// hard.
			log.Fatal(err)
		} else {
			// Default config file missing; just warn.
			log.Print(err)
		}
	} else {
		if err = json.Unmarshal(configData, &config); err != nil {
			log.Fatal(err)
		}
	}

	// Final merge into settings object.
	if settings.Address == "" {
		if config.Address != "" {
			settings.Address = config.Address
		} else {
			settings.Address = defaults.Address
		}
	}
	if settings.Logfile == "" {
		if config.Logfile != "" {
			settings.Logfile = config.Logfile
		} else {
			settings.Logfile = defaults.Logfile
		}
	}
	if settings.Port == 0 {
		if config.Port != 0 {
			settings.Port = config.Port
		} else {
			settings.Port = defaults.Port
		}
	}

	expandedPath = expandPath(settings.Logfile)
	outfile, err := os.OpenFile(expandedPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		log.Fatal(err)
	}
	defer outfile.Close()
	log.SetOutput(outfile)

	if _, err := exec.LookPath(pbcopy); err != nil {
		log.Fatal(err)
	}

	var addr string
	var listenType string
	if isPath(config.Address) {
		addr = expandPath(config.Address)
	} else if isPath(settings.Address) {
		addr = expandPath(settings.Address)
	} else {
		addr = settings.Address
	}
	if strings.HasPrefix(addr, "/") {
		log.Print("Starting UNIX domain socket server at ", addr)
		listenType = "unix"
	} else {
		log.Print("Starting TCP server on ", addr)
		listenType = "tcp"
		addr = fmt.Sprintf("%s:%d", settings.Address, settings.Port)
	}
	listener, err := net.Listen(listenType, addr)
	if err != nil {
		log.Fatal(err)
	}
	defer listener.Close()

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				log.Print(err)
				return
			}

			go handleConnection(conn)
		}
	}()

	// Need to catch signals in order for `defer`-ed clean-up items to run.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM)
	sig := <-c
	log.Print("Got signal ", sig)
}

// Returns true for things which look like paths (start with "~", "." or "/").
func isPath(path string) bool {
	return strings.HasPrefix(path, "~") ||
		strings.HasPrefix(path, ".") ||
		strings.HasPrefix(path, "/")
}

func expandPath(path string) string {
	expanded := pathByExpandingTildeInPath(path)
	result, err := filepath.Abs(expanded)
	if err != nil {
		log.Fatal(err)
	}
	return result
}

func pathByExpandingTildeInPath(path string) string {
	if strings.HasPrefix(path, "~") {
		user, err := user.Current()
		if err != nil {
			log.Fatal(err)
		}
		path = user.HomeDir + path[1:]
	}
	return path
}

func handleConnection(conn net.Conn) {
	defer log.Print("Connection closed")
	defer conn.Close()

	cmd := exec.Command(pbcopy)
	stdin, err := cmd.StdinPipe()
	if err != nil {
		log.Print(err)
		return
	}
	if err = cmd.Start(); err != nil {
		log.Print(err)
		return
	}

	if copied, err := io.Copy(stdin, conn); err != nil {
		log.Print(err)
	} else {
		log.Print("Echoed ", copied, " bytes")
	}
	stdin.Close()

	if err = cmd.Wait(); err != nil {
		log.Print(err)
	}
}
<|endoftext|>


<commit_before>package tests

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

	log "github.com/Sirupsen/logrus"

	"github.com/quilt/quilt/stitch"
)

// workDir is the directory blueprints are placed during testing.
const workDir = "/tmp/quilt-blueprint-test"

func tryRunBlueprint(s blueprint) error {
	os.Mkdir(workDir, 0755)
	defer os.RemoveAll(workDir)
	os.Chdir(workDir)

	if err := run("git", "clone", s.repo, "."); err != nil {
		return err
	}

	if err := run("npm", "install", s.packageJsonFolder); err != nil {
		return err
	}

	_, err := stitch.FromFile(s.blueprintPath)
	return err
}

func run(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	stderr := bytes.NewBuffer(nil)
	cmd.Stderr = stderr
	if cmd.Run() != nil {
		return errors.New(stderr.String())
	}
	return nil
}

type blueprint struct {
	repo, packageJsonFolder, blueprintPath string
}

// TestBlueprints checks that the listed Quilt blueprints compile.
func TestBlueprints() error {
	blueprints := []blueprint{
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/100-logs/logs.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/61-duplicate-cluster/duplicate-cluster.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/60-duplicate-cluster-setup/" +
				"duplicate-cluster-setup.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/40-stop/stop.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/30-mean/mean.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/20-spark/spark.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/15-bandwidth/bandwidth.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/10-network/network.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/outbound-public/outbound-public.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/inbound-public/inbound-public.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/elasticsearch/elasticsearch.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/build-dockerfile/build-dockerfile.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/etcd/etcd.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/zookeeper/zookeeper.js"},

		{"https://github.com/quilt/nginx", ".", "./main.js"},
		{"https://github.com/quilt/spark", ".", "./sparkPI.js"},
		{"https://github.com/quilt/wordpress", ".", "./wordpress-example.js"},
		{"https://github.com/quilt/etcd", ".", "./etcd-example.js"},
		{"https://github.com/quilt/zookeeper", ".", "./zookeeper-example.js"},
		{"https://github.com/quilt/redis", ".", "./redis-example.js"},
		{"https://github.com/quilt/mean", ".", "./example.js"},
		{"https://github.com/quilt/elasticsearch", ".", "./main.js"},
		{"https://github.com/quilt/kibana", ".", "./main.js"},
		{"https://github.com/quilt/django", ".", "./django-example.js"},
		{"https://github.com/quilt/php-apache", ".", "./main.js"},
		{"https://github.com/quilt/mongo", ".", "./example.js"},
		{"https://github.com/quilt/tester", ".", "./tester-runner-example.js"},
		{"https://github.com/quilt/lobsters", ".", "./lobsters-example.js"},
		{"https://github.com/quilt/infrastructure", ".", "./floating-ip.js"},
	}

	for _, s := range blueprints {
		log.Infof("Testing %s in %s", s.blueprintPath, s.repo)
		if err := tryRunBlueprint(s); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>blueprints-tester: Fix lint error<commit_after>package tests

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

	log "github.com/Sirupsen/logrus"

	"github.com/quilt/quilt/stitch"
)

// workDir is the directory blueprints are placed during testing.
const workDir = "/tmp/quilt-blueprint-test"

func tryRunBlueprint(s blueprint) error {
	os.Mkdir(workDir, 0755)
	defer os.RemoveAll(workDir)
	os.Chdir(workDir)

	if err := run("git", "clone", s.repo, "."); err != nil {
		return err
	}

	if err := run("npm", "install", s.packageJSONFolder); err != nil {
		return err
	}

	_, err := stitch.FromFile(s.blueprintPath)
	return err
}

func run(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	stderr := bytes.NewBuffer(nil)
	cmd.Stderr = stderr
	if cmd.Run() != nil {
		return errors.New(stderr.String())
	}
	return nil
}

type blueprint struct {
	repo, packageJSONFolder, blueprintPath string
}

// TestBlueprints checks that the listed Quilt blueprints compile.
func TestBlueprints() error {
	blueprints := []blueprint{
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/100-logs/logs.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/61-duplicate-cluster/duplicate-cluster.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/60-duplicate-cluster-setup/" +
				"duplicate-cluster-setup.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/40-stop/stop.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/30-mean/mean.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/20-spark/spark.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/15-bandwidth/bandwidth.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/10-network/network.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/outbound-public/outbound-public.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/inbound-public/inbound-public.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/elasticsearch/elasticsearch.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/build-dockerfile/build-dockerfile.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/etcd/etcd.js"},
		{"https://github.com/quilt/quilt", "./quilt-tester",
			"./quilt-tester/tests/zookeeper/zookeeper.js"},

		{"https://github.com/quilt/nginx", ".", "./main.js"},
		{"https://github.com/quilt/spark", ".", "./sparkPI.js"},
		{"https://github.com/quilt/wordpress", ".", "./wordpress-example.js"},
		{"https://github.com/quilt/etcd", ".", "./etcd-example.js"},
		{"https://github.com/quilt/zookeeper", ".", "./zookeeper-example.js"},
		{"https://github.com/quilt/redis", ".", "./redis-example.js"},
		{"https://github.com/quilt/mean", ".", "./example.js"},
		{"https://github.com/quilt/elasticsearch", ".", "./main.js"},
		{"https://github.com/quilt/kibana", ".", "./main.js"},
		{"https://github.com/quilt/django", ".", "./django-example.js"},
		{"https://github.com/quilt/php-apache", ".", "./main.js"},
		{"https://github.com/quilt/mongo", ".", "./example.js"},
		{"https://github.com/quilt/tester", ".", "./tester-runner-example.js"},
		{"https://github.com/quilt/lobsters", ".", "./lobsters-example.js"},
		{"https://github.com/quilt/infrastructure", ".", "./floating-ip.js"},
	}

	for _, s := range blueprints {
		log.Infof("Testing %s in %s", s.blueprintPath, s.repo)
		if err := tryRunBlueprint(s); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"time"

	"github.com/PonyvilleFM/aura/bot"
	"github.com/PonyvilleFM/aura/commands/source"
	"github.com/bwmarrin/discordgo"
	_ "github.com/joho/godotenv/autoload"
)

type aerial struct {
	cs *bot.CommandSet
	s  *discordgo.Session
}

const (
	djonHelp  = ``
	djoffHelp = ``
	setupHelp = ``
)

func (a *aerial) Handle(s *discordgo.Session, m *discordgo.MessageCreate) {
	err := a.cs.Run(s, m.Message)
	if err != nil {
		log.Println(err)
	}
}

var (
	token             = os.Getenv("TOKEN")
	youtubeSpamRoomID = os.Getenv("DISCORD_YOUTUBESPAM_ROOMID")
	gClientID         = os.Getenv("GOOGLE_CLIENT_ID")
	gClientSecret     = os.Getenv("GOOGLE_CLIENT_SECRET")

	musicLinkRegex = regexp.MustCompile(`(.*)((http(s?):\/\/(www\.)?soundcloud.com\/.*)|(http(s?):\/\/(www\.)?youtube.com\/.*)|(http(s?):\/\/(www\.)?youtu.be\/.*))(.*)|(.*)http(s?):\/\/(www\.)?mixcloud.com\/.*`)
)

func main() {
	flag.Parse()
	dg, err := discordgo.New("Bot " + token)
	if err != nil {
		log.Fatal(err)
	}

	a := &aerial{
		cs: bot.NewCommandSet(),
		s:  dg,
	}

	a.cs.Prefix = ";"
	a.cs.AddCmd("dhelp", "__Recommended to use not to help-spam the channel__ sends help to your direct messages", bot.NoPermissions, dhelp)
	a.cs.AddCmd("np", "shows radio station statistics for Ponyville FM", bot.NoPermissions, stats)
	a.cs.AddCmd("stats", "shows radio station statistics for Ponyville FM", bot.NoPermissions, stats)
	a.cs.AddCmd("dj", "shows which DJ is up next on Ponyville FM", bot.NoPermissions, stats)
	a.cs.AddCmd("schedule", "shows the future radio schedule for Ponyville FM", bot.NoPermissions, schedule)
	a.cs.AddCmd("printerfact", "shows useful facts about printers", bot.NoPermissions, printerFact)
	a.cs.AddCmd("hipster", "hip me up fam", bot.NoPermissions, hipster)
	a.cs.AddCmd("source", "source code information", bot.NoPermissions, source.Source)
	a.cs.AddCmd("time", "shows the current bot time", bot.NoPermissions, curTime)
	a.cs.AddCmd("streams", "shows the different Ponyville FM stream links", bot.NoPermissions, streams)
	a.cs.AddCmd("servers", "shows the different Ponyville FM stream links", bot.NoPermissions, streams)
	a.cs.AddCmd("derpi", "grabs a random **__safe__** image from Derpibooru with the given search results", bot.NoPermissions, derpi)
	a.cs.AddCmd("weather", "how's the weather right now?", bot.NoPermissions, weather)

	dg.AddHandler(a.Handle)
	dg.AddHandler(pesterLink)
	dg.AddHandler(messageCreate)
	dg.AddHandler(imageMeEvent)

	err = dg.Open()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("ready")

	<-make(chan struct{})
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	// Print message to stdout.
	fmt.Printf("%20s %20s %20s > %s\n", m.ChannelID, time.Now().Format(time.Stamp), m.Author.Username, m.Content)
}
<commit_msg>Deleted `dhelp` from aerial commands<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"regexp"
	"time"

	"github.com/PonyvilleFM/aura/bot"
	"github.com/PonyvilleFM/aura/commands/source"
	"github.com/bwmarrin/discordgo"
	_ "github.com/joho/godotenv/autoload"
)

type aerial struct {
	cs *bot.CommandSet
	s  *discordgo.Session
}

const (
	djonHelp  = ``
	djoffHelp = ``
	setupHelp = ``
)

func (a *aerial) Handle(s *discordgo.Session, m *discordgo.MessageCreate) {
	err := a.cs.Run(s, m.Message)
	if err != nil {
		log.Println(err)
	}
}

var (
	token             = os.Getenv("TOKEN")
	youtubeSpamRoomID = os.Getenv("DISCORD_YOUTUBESPAM_ROOMID")
	gClientID         = os.Getenv("GOOGLE_CLIENT_ID")
	gClientSecret     = os.Getenv("GOOGLE_CLIENT_SECRET")

	musicLinkRegex = regexp.MustCompile(`(.*)((http(s?):\/\/(www\.)?soundcloud.com\/.*)|(http(s?):\/\/(www\.)?youtube.com\/.*)|(http(s?):\/\/(www\.)?youtu.be\/.*))(.*)|(.*)http(s?):\/\/(www\.)?mixcloud.com\/.*`)
)

func main() {
	flag.Parse()
	dg, err := discordgo.New("Bot " + token)
	if err != nil {
		log.Fatal(err)
	}

	a := &aerial{
		cs: bot.NewCommandSet(),
		s:  dg,
	}

	a.cs.Prefix = ";"
	a.cs.AddCmd("np", "shows radio station statistics for Ponyville FM", bot.NoPermissions, stats)
	a.cs.AddCmd("stats", "shows radio station statistics for Ponyville FM", bot.NoPermissions, stats)
	a.cs.AddCmd("dj", "shows which DJ is up next on Ponyville FM", bot.NoPermissions, stats)
	a.cs.AddCmd("schedule", "shows the future radio schedule for Ponyville FM", bot.NoPermissions, schedule)
	a.cs.AddCmd("printerfact", "shows useful facts about printers", bot.NoPermissions, printerFact)
	a.cs.AddCmd("hipster", "hip me up fam", bot.NoPermissions, hipster)
	a.cs.AddCmd("source", "source code information", bot.NoPermissions, source.Source)
	a.cs.AddCmd("time", "shows the current bot time", bot.NoPermissions, curTime)
	a.cs.AddCmd("streams", "shows the different Ponyville FM stream links", bot.NoPermissions, streams)
	a.cs.AddCmd("servers", "shows the different Ponyville FM stream links", bot.NoPermissions, streams)
	a.cs.AddCmd("derpi", "grabs a random **__safe__** image from Derpibooru with the given search results", bot.NoPermissions, derpi)
	a.cs.AddCmd("weather", "how's the weather right now?", bot.NoPermissions, weather)

	dg.AddHandler(a.Handle)
	dg.AddHandler(pesterLink)
	dg.AddHandler(messageCreate)
	dg.AddHandler(imageMeEvent)

	err = dg.Open()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("ready")

	<-make(chan struct{})
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	// Print message to stdout.
	fmt.Printf("%20s %20s %20s > %s\n", m.ChannelID, time.Now().Format(time.Stamp), m.Author.Username, m.Content)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"math/rand"
	"sync"
	"time"

	"github.com/bwmarrin/discordgo"
)

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

var (
	ulock          sync.Mutex
	raffleUsers    map[string]map[string]struct{}
	raffleSessions map[string]string
)

func raffleStart(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	raffleSessions[m.ChannelID] = m.Author.ID
	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("<@%s> created a new raffle! Type %senter to enter!", m.Author.ID, ";"))

	return nil
}

func rafflePop(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	creator, ok := raffleSessions[m.ChannelID]
	if !ok {
		return errors.New("no raffle currently running")
	}

	if m.Author.ID != creator {
		return fmt.Errorf("you are not <@%s>, you cannot end this raffle", creator)
	}

	cmap, ok := raffleUsers[m.ChannelID]
	if !ok {
		cmap = map[string]struct{}{}
	}

	users := []string{}
	for u := range cmap {
		users = append(users, u)
	}
	i := rand.Intn(len(users))
	u := users[i]

	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Congrats <@%s>, you won!", u))

	delete(cmap, u)
	raffleUsers[m.ChannelID] = cmap
}

func raffleEnd(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	creator, ok := raffleSessions[m.ChannelID]
	if !ok {
		return errors.New("no raffle currently running")
	}

	if m.Author.ID != creator {
		return fmt.Errorf("you are not <@%s>, you cannot end this raffle", creator)
	}

	delete(raffleUsers, m.ChannelID)
	delete(raffleSessions, m.ChannelID)

	s.ChannelMessageSend(m.ChannelID, "Raffle destroyed.")

	return nil
}

func raffle(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	_, ok := raffleSessions[m.ChannelID]
	if !ok {
		return errors.New("no raffle currently running")
	}

	cmap, ok := raffleUsers[m.ChannelID]
	if !ok {
		cmap = map[string]struct{}{}
	}

	_, ok = cmap[m.Author.ID]
	if ok {
		return errors.New("you already joined this raffle, you can't join it again")
	}

	cmap[m.Author.ID] = struct{}{}
	raffleUsers[m.ChannelID] = cmap

	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("<@%s>: your entry has been recorded!", m.Author.ID))
	return nil
}
<commit_msg>cmd/aerial: typo again<commit_after>package main

import (
	"errors"
	"fmt"
	"math/rand"
	"sync"
	"time"

	"github.com/bwmarrin/discordgo"
)

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

var (
	ulock          sync.Mutex
	raffleUsers    map[string]map[string]struct{}
	raffleSessions map[string]string
)

func raffleStart(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	raffleSessions[m.ChannelID] = m.Author.ID
	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("<@%s> created a new raffle! Type %senter to enter!", m.Author.ID, ";"))

	return nil
}

func rafflePop(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	creator, ok := raffleSessions[m.ChannelID]
	if !ok {
		return errors.New("no raffle currently running")
	}

	if m.Author.ID != creator {
		return fmt.Errorf("you are not <@%s>, you cannot select a winner", creator)
	}

	cmap, ok := raffleUsers[m.ChannelID]
	if !ok {
		cmap = map[string]struct{}{}
	}

	users := []string{}
	for u := range cmap {
		users = append(users, u)
	}
	i := rand.Intn(len(users))
	u := users[i]

	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Congrats <@%s>, you won!", u))

	delete(cmap, u)
	raffleUsers[m.ChannelID] = cmap
}

func raffleEnd(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	creator, ok := raffleSessions[m.ChannelID]
	if !ok {
		return errors.New("no raffle currently running")
	}

	if m.Author.ID != creator {
		return fmt.Errorf("you are not <@%s>, you cannot end this raffle", creator)
	}

	delete(raffleUsers, m.ChannelID)
	delete(raffleSessions, m.ChannelID)

	s.ChannelMessageSend(m.ChannelID, "Raffle destroyed.")

	return nil
}

func raffle(s *discordgo.Session, m *discordgo.Message, parv []string) error {
	ulock.Lock()
	defer ulock.Unlock()

	_, ok := raffleSessions[m.ChannelID]
	if !ok {
		return errors.New("no raffle currently running")
	}

	cmap, ok := raffleUsers[m.ChannelID]
	if !ok {
		cmap = map[string]struct{}{}
	}

	_, ok = cmap[m.Author.ID]
	if ok {
		return errors.New("you already joined this raffle, you can't join it again")
	}

	cmap[m.Author.ID] = struct{}{}
	raffleUsers[m.ChannelID] = cmap

	s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("<@%s>: your entry has been recorded!", m.Author.ID))
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/pkg/errors"
	"github.com/projectatomic/buildah/pkg/parse"
	"github.com/projectatomic/buildah/util"
	"github.com/urfave/cli"
)

var (
	mountDescription = "Mounts a working container's root filesystem for manipulation"
	mountFlags       = []cli.Flag{
		cli.BoolFlag{
			Name:  "notruncate",
			Usage: "do not truncate output",
		},
	}
	mountCommand = cli.Command{
		Name:           "mount",
		Usage:          "Mount a working container's root filesystem",
		Description:    mountDescription,
		Action:         mountCmd,
		ArgsUsage:      "[CONTAINER-NAME-OR-ID [...]]",
		Flags:          mountFlags,
		SkipArgReorder: true,
	}
)

func mountCmd(c *cli.Context) error {
	args := c.Args()

	if err := parse.ValidateFlags(c, mountFlags); err != nil {
		return err
	}

	store, err := getStore(c)
	if err != nil {
		return err
	}
	truncate := !c.Bool("notruncate")

	var lastError error
	if len(args) > 0 {
		for _, name := range args {
			builder, err := openBuilder(getContext(), store, name)
			if err != nil {
				lastError = util.WriteError(os.Stderr, errors.Wrapf(err, "error reading build container %q", name), lastError)
				continue
			}
			mountPoint, err := builder.Mount(builder.MountLabel)
			if err != nil {
				lastError = util.WriteError(os.Stderr, errors.Wrapf(err, "error mounting %q container %q", name, builder.Container), lastError)
				continue
			}
			if len(args) > 1 {
				fmt.Printf("%s %s\n", name, mountPoint)
			} else {
				fmt.Printf("%s\n", mountPoint)
			}
		}
	} else {
		builders, err := openBuilders(store)
		if err != nil {
			return errors.Wrapf(err, "error reading build containers")
		}
		for _, builder := range builders {
			if builder.MountPoint == "" {
				continue
			}
			if truncate {
				fmt.Printf("%-12.12s %s\n", builder.ContainerID, builder.MountPoint)
			} else {
				fmt.Printf("%-64s %s\n", builder.ContainerID, builder.MountPoint)
			}
		}
	}
	return lastError
}
<commit_msg>mount: output it before replacing lastError<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/pkg/errors"
	"github.com/projectatomic/buildah/pkg/parse"
	"github.com/projectatomic/buildah/util"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

var (
	mountDescription = "Mounts a working container's root filesystem for manipulation"
	mountFlags       = []cli.Flag{
		cli.BoolFlag{
			Name:  "notruncate",
			Usage: "do not truncate output",
		},
	}
	mountCommand = cli.Command{
		Name:           "mount",
		Usage:          "Mount a working container's root filesystem",
		Description:    mountDescription,
		Action:         mountCmd,
		ArgsUsage:      "[CONTAINER-NAME-OR-ID [...]]",
		Flags:          mountFlags,
		SkipArgReorder: true,
	}
)

func mountCmd(c *cli.Context) error {
	args := c.Args()

	if err := parse.ValidateFlags(c, mountFlags); err != nil {
		return err
	}

	store, err := getStore(c)
	if err != nil {
		return err
	}
	truncate := !c.Bool("notruncate")

	var lastError error
	if len(args) > 0 {
		for _, name := range args {
			builder, err := openBuilder(getContext(), store, name)
			if err != nil {
				if lastError != nil {
					logrus.Error(lastError)
				}
				lastError = util.WriteError(os.Stderr, errors.Wrapf(err, "error reading build container %q", name), lastError)
				continue
			}
			mountPoint, err := builder.Mount(builder.MountLabel)
			if err != nil {
				if lastError != nil {
					logrus.Error(lastError)
				}
				lastError = util.WriteError(os.Stderr, errors.Wrapf(err, "error mounting %q container %q", name, builder.Container), lastError)
				continue
			}
			if len(args) > 1 {
				fmt.Printf("%s %s\n", name, mountPoint)
			} else {
				fmt.Printf("%s\n", mountPoint)
			}
		}
	} else {
		builders, err := openBuilders(store)
		if err != nil {
			return errors.Wrapf(err, "error reading build containers")
		}
		for _, builder := range builders {
			if builder.MountPoint == "" {
				continue
			}
			if truncate {
				fmt.Printf("%-12.12s %s\n", builder.ContainerID, builder.MountPoint)
			} else {
				fmt.Printf("%-64s %s\n", builder.ContainerID, builder.MountPoint)
			}
		}
	}
	return lastError
}
<|endoftext|>