<commit_before>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
)

const (
	cormFilename = "Cormfile"
	cormDir      = "_corm"
)

var (
	currentDir     string
	dirtyVendorDir string
	cormfile       string
)

var errCannotParseLine = errors.New("cannot parse line")

var vcsMetaDir = []string{".svn", ".git", ".hg"}

type repository struct {
	Path   string
	Commit string
}

func parse(s string) (*repository, error) {
	// TODO: Consider the format
	fields := strings.Fields(s)
	switch len(fields) {
	case 1:
		return &repository{Path: fields[0]}, nil
	case 2:
		return &repository{Path: fields[0], Commit: fields[1]}, nil
	default:
		return nil, errCannotParseLine
	}
}

func exists(filepath string) bool {
	_, err := os.Stat(filepath)
	return err == nil
}

func readCorm(filepath string) ([]*repository, error) {
	f, err := os.Open(filepath)
	if err != nil {
		return nil, fmt.Errorf("cannot open Cormfile: %s", err)
	}
	defer f.Close()

	repos := make([]*repository, 0, 30)

	s := bufio.NewScanner(f)
	for s.Scan() {
		line := s.Text()
		if line == "" {
			continue
		}

		repo, err := parse(line)
		if err != nil {
			fmt.Fprintf(os.Stderr, "SKIPPED: %s: %s\n", err, line)
			continue
		}
		repos = append(repos, repo)
	}

	return repos, nil
}

func goGet(repo *repository) error {
	// TODO: can handle options for `go get`
	fmt.Printf("go get %s\n", repo.Path)
	cmd := exec.Command("go", "get", repo.Path)
	cmd.Stdout = os.Stdout
	err := cmd.Run()
	// Commit が指定されている場合の処理は後で実装する
	return err
}

func newCopyFileFun(srcBase string, destBase string) filepath.WalkFunc {

	return func(srcPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		relPath, err := filepath.Rel(srcBase, srcPath)
		if err != nil {
			return err
		}

		destPath := filepath.Join(destBase, relPath)

		if info.IsDir() {
			index := sort.SearchStrings(vcsMetaDir, info.Name())
			if index < len(vcsMetaDir) {
				return filepath.SkipDir
			}

			return os.MkdirAll(destPath, info.Mode())
		}

		if exists(destPath) {
			return nil
		}

		return os.Link(srcPath, destPath)
	}

}

func export(src string, dest string) error {
	copyFile := newCopyFileFun(src, dest)
	err := filepath.Walk(src, copyFile)
	return err
}

func init() {
	var err error
	currentDir, err = os.Getwd()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot get current directory")
		os.Exit(1)
	}

	dirtyVendorDir = filepath.Join(currentDir, cormDir)
}

func fakeGopath() {

	// if target package exists default GOPATH, then go get does nothing.
	// So, set GOPATH dirtyVendorDir only

	os.Setenv("GOPATH", dirtyVendorDir)

}

func mainCmd() int {
	repos, err := readCorm(cormfile)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if len(repos) == 0 {
		fmt.Fprintln(os.Stderr, "no repositories in Cormfile")
		return 1
	}

	fakeGopath()
	for _, repo := range repos {
		err := goGet(repo)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cannot exec go get: %s, %s\n", repo.Path, err)
		}
	}

	return 0
}

func exportCmd() int {
	dirtyVendorSrcDir := filepath.Join(dirtyVendorDir, "src")

	if !exists(dirtyVendorDir) {
		fmt.Fprintf(os.Stderr, "%s does not exists\n", dirtyVendorSrcDir)
		return 1
	}

	cleanVendorDir := filepath.Join(currentDir, "vendor")
	err := export(dirtyVendorSrcDir, cleanVendorDir)
	if err != nil {
		fmt.Fprintln(os.Stderr, "export error:", err)
		return 1
	}

	return 0
}

func execCmd(args []string) int {
	if len(args) == 0 {
		fmt.Fprintln(os.Stderr, "no exec target command")
		return 1
	}

	fakeGopath()
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// TODO: cant exec vim main.go
	err := cmd.Run()
	if err != nil {
		fmt.Fprintln(os.Stderr, "exec error:", err)
		return 1
	}
	return 0
}

func goSubCmd(sub string, args []string) error {
	fakeGopath()
	args = append([]string{sub}, args...)
	cmd := exec.Command("go", args...)
	err := cmd.Run()

	if err != nil {
		fmt.Fprintln(os.Stderr, sub, "error:", err)
		return err
	}

	return nil
}

func buildCmd(args []string) int {
	err := goSubCmd("build", args)
	if err != nil {
		return 1
	}

	return 0
}

func testCmd(args []string) int {
	err := goSubCmd("test", args)
	if err != nil {
		return 1
	}

	return 0
}

func usage() int {
	fmt.Println(`Usage: corm command
	install	:	install packages from Cormfile.
	export	:	export packages to vendor directory.
	exec    :   exec command with faked GOPATH.
	build   :   build files with vendor libraries.
	test    :   test files with vendor libraries.`)

	return 1
}

func main() {
	sort.Strings(vcsMetaDir)

	if len(os.Args) == 1 {
		os.Exit(usage())
	}

	cormfile = filepath.Join(currentDir, cormFilename)
	if !exists(cormfile) {
		fmt.Fprintf(os.Stderr, "%s does not exists\n", cormfile)
		os.Exit(1)
	}

	command := os.Args[1]

	switch command {
	case "install":
		os.Exit(mainCmd())
	case "export":
		os.Exit(exportCmd())
	case "exec":
		os.Exit(execCmd(os.Args[2:]))
	case "build":
		os.Exit(buildCmd(os.Args[2:]))
	case "test":
		os.Exit(testCmd(os.Args[2:]))
	default:
		os.Exit(usage())
	}
}
<commit_msg>fix spaces<commit_after>package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
)

const (
	cormFilename = "Cormfile"
	cormDir      = "_corm"
)

var (
	currentDir     string
	dirtyVendorDir string
	cormfile       string
)

var errCannotParseLine = errors.New("cannot parse line")

var vcsMetaDir = []string{".svn", ".git", ".hg"}

type repository struct {
	Path   string
	Commit string
}

func parse(s string) (*repository, error) {
	// TODO: Consider the format
	fields := strings.Fields(s)
	switch len(fields) {
	case 1:
		return &repository{Path: fields[0]}, nil
	case 2:
		return &repository{Path: fields[0], Commit: fields[1]}, nil
	default:
		return nil, errCannotParseLine
	}
}

func exists(filepath string) bool {
	_, err := os.Stat(filepath)
	return err == nil
}

func readCorm(filepath string) ([]*repository, error) {
	f, err := os.Open(filepath)
	if err != nil {
		return nil, fmt.Errorf("cannot open Cormfile: %s", err)
	}
	defer f.Close()

	repos := make([]*repository, 0, 30)

	s := bufio.NewScanner(f)
	for s.Scan() {
		line := s.Text()
		if line == "" {
			continue
		}

		repo, err := parse(line)
		if err != nil {
			fmt.Fprintf(os.Stderr, "SKIPPED: %s: %s\n", err, line)
			continue
		}
		repos = append(repos, repo)
	}

	return repos, nil
}

func goGet(repo *repository) error {
	// TODO: can handle options for `go get`
	fmt.Printf("go get %s\n", repo.Path)
	cmd := exec.Command("go", "get", repo.Path)
	cmd.Stdout = os.Stdout
	err := cmd.Run()
	// Commit が指定されている場合の処理は後で実装する
	return err
}

func newCopyFileFun(srcBase string, destBase string) filepath.WalkFunc {

	return func(srcPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		relPath, err := filepath.Rel(srcBase, srcPath)
		if err != nil {
			return err
		}

		destPath := filepath.Join(destBase, relPath)

		if info.IsDir() {
			index := sort.SearchStrings(vcsMetaDir, info.Name())
			if index < len(vcsMetaDir) {
				return filepath.SkipDir
			}

			return os.MkdirAll(destPath, info.Mode())
		}

		if exists(destPath) {
			return nil
		}

		return os.Link(srcPath, destPath)
	}

}

func export(src string, dest string) error {
	copyFile := newCopyFileFun(src, dest)
	err := filepath.Walk(src, copyFile)
	return err
}

func init() {
	var err error
	currentDir, err = os.Getwd()
	if err != nil {
		fmt.Fprintln(os.Stderr, "cannot get current directory")
		os.Exit(1)
	}

	dirtyVendorDir = filepath.Join(currentDir, cormDir)
}

func fakeGopath() {

	// if target package exists default GOPATH, then go get does nothing.
	// So, set GOPATH dirtyVendorDir only

	os.Setenv("GOPATH", dirtyVendorDir)

}

func mainCmd() int {
	repos, err := readCorm(cormfile)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if len(repos) == 0 {
		fmt.Fprintln(os.Stderr, "no repositories in Cormfile")
		return 1
	}

	fakeGopath()
	for _, repo := range repos {
		err := goGet(repo)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cannot exec go get: %s, %s\n", repo.Path, err)
		}
	}

	return 0
}

func exportCmd() int {
	dirtyVendorSrcDir := filepath.Join(dirtyVendorDir, "src")

	if !exists(dirtyVendorDir) {
		fmt.Fprintf(os.Stderr, "%s does not exists\n", dirtyVendorSrcDir)
		return 1
	}

	cleanVendorDir := filepath.Join(currentDir, "vendor")
	err := export(dirtyVendorSrcDir, cleanVendorDir)
	if err != nil {
		fmt.Fprintln(os.Stderr, "export error:", err)
		return 1
	}

	return 0
}

func execCmd(args []string) int {
	if len(args) == 0 {
		fmt.Fprintln(os.Stderr, "no exec target command")
		return 1
	}

	fakeGopath()
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// TODO: cant exec vim main.go
	err := cmd.Run()
	if err != nil {
		fmt.Fprintln(os.Stderr, "exec error:", err)
		return 1
	}
	return 0
}

func goSubCmd(sub string, args []string) error {
	fakeGopath()
	args = append([]string{sub}, args...)
	cmd := exec.Command("go", args...)
	err := cmd.Run()

	if err != nil {
		fmt.Fprintln(os.Stderr, sub, "error:", err)
		return err
	}

	return nil
}

func buildCmd(args []string) int {
	err := goSubCmd("build", args)
	if err != nil {
		return 1
	}

	return 0
}

func testCmd(args []string) int {
	err := goSubCmd("test", args)
	if err != nil {
		return 1
	}

	return 0
}

func usage() int {
	fmt.Println(`Usage: corm command
	install	:    install packages from Cormfile.
	export	:    export packages to vendor directory.
	exec    :    exec command with faked GOPATH.
	build   :    build files with vendor libraries.
	test    :    test files with vendor libraries.`)

	return 1
}

func main() {
	sort.Strings(vcsMetaDir)

	if len(os.Args) == 1 {
		os.Exit(usage())
	}

	cormfile = filepath.Join(currentDir, cormFilename)
	if !exists(cormfile) {
		fmt.Fprintf(os.Stderr, "%s does not exists\n", cormfile)
		os.Exit(1)
	}

	command := os.Args[1]

	switch command {
	case "install":
		os.Exit(mainCmd())
	case "export":
		os.Exit(exportCmd())
	case "exec":
		os.Exit(execCmd(os.Args[2:]))
	case "build":
		os.Exit(buildCmd(os.Args[2:]))
	case "test":
		os.Exit(testCmd(os.Args[2:]))
	default:
		os.Exit(usage())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"github.com/cenkalti/backoff"
	"github.com/pivotal-cf/rabbitmq-upgrade-preparation/rabbitmqctl"
	"github.com/pivotal-cf/rabbitmq-upgrade-preparation/versions"
)

func main() {
	logger := log.New(os.Stdout, "", 0)
	log.SetFlags(0)

	args := parseArgs()

	logger.Printf("Checking whether upgrade preparation is necessary for %s\n", args.node)
	rabbitMQCtl := rabbitmqctl.New(args.rabbitmqctlPath)

	backOffStrategy := backoff.NewExponentialBackOff()
	backOffStrategy.MaxElapsedTime = args.timeout
	backOffStrategy.InitialInterval = 100 * time.Millisecond

	var status rabbitmqctl.RabbitMQCtlStatus
	var statusErr error
	var retryCount int

	operation := func() error {
		retryCount++
		logger.Printf("Trying to connect to %s...\n", args.node)
		status, statusErr = rabbitMQCtl.Status(args.node)
		if statusErr != nil {
			err := statusErr.(*rabbitmqctl.Error)

			if err.Status == rabbitmqctl.UnreachableEpmd || err.Status == rabbitmqctl.StoppedRabbitNode {
				logger.Printf("RabbitMQ %s already stopped: %s\n", args.node, err)
				return nil
			}
		}

		if backOffStrategy.NextBackOff() != backoff.Stop {
			logger.Printf("Failed to connect to %s after %d retries, retrying in %s\n", args.node, retryCount, backOffStrategy.NextBackOff())
		}
		return statusErr
	}
	retryErr := backoff.Retry(operation, backOffStrategy)

	if retryErr != nil {
		err := retryErr.(*rabbitmqctl.Error)
		if err.Status == rabbitmqctl.UnreachableHost {
			log.Fatalf("Unable to connect to node %s after %d retries within %v: %s", args.node, retryCount, args.timeout, err)
		}
	}

	deployedRabbitVersion, ok := status.RabbitMQVersion()
	if !ok {
		logger.Printf("Safe to proceed without stopping RabbitMQ %s application, exiting: RabbitMQ application already stopped\n", args.node)
		return
	}

	deployedErlangVersion, _ := status.ErlangVersion()

	differences := []versions.VersionDifference{
		&versions.RabbitVersions{Desired: args.desiredRabbitMQVersion, Deployed: deployedRabbitVersion},
		&versions.ErlangVersions{Desired: args.desiredErlangVersion, Deployed: deployedErlangVersion},
	}

	for _, difference := range differences {
		logger.Printf("%s\n", difference.UpgradeMessage())
		if difference.PreparationRequired() {
			logger.Println("The cluster needs to be taken offline as it cannot run in mixed mode")
			logger.Printf("Stopping RabbitMQ on %s\n", args.node)
			if err := rabbitMQCtl.StopApp(args.node); err != nil {
				log.Fatalf("Failed to stop RabbitMQ on %s: %s", args.node, err)
			}
			return
		}
	}
	logger.Println("Safe to proceed without taking the cluster offline")
}

type Args struct {
	rabbitmqctlPath        string
	node                   string
	desiredRabbitMQVersion string
	desiredErlangVersion   string
	timeout                time.Duration
}

func parseArgs() Args {
	rabbitmqctlPath := flag.String("rabbitmqctl-path", "", "Path to rabbitmqctl")
	node := flag.String("node", "", "RabbitMQ node to prepare")
	newRabbitmqVersion := flag.String("new-rabbitmq-version", "", "Version of RabbitMQ that we are upgrading to")
	newErlangVersion := flag.String("new-erlang-version", "", "Version of Erlang that we are upgrading to")
	timeout := flag.Duration("timeout", 60*time.Second, "Maximum time in seconds that you allow rabbitmqctl status to take")
	flag.Parse()

	assertFlag(*rabbitmqctlPath, "rabbitmqctl-path")
	assertFlag(*node, "node")
	assertFlag(*newRabbitmqVersion, "new-rabbitmq-version")
	assertFlag(*newErlangVersion, "new-erlang-version")

	return Args{
		rabbitmqctlPath: *rabbitmqctlPath,
		node:            *node,
		desiredRabbitMQVersion: *newRabbitmqVersion,
		desiredErlangVersion:   *newErlangVersion,
		timeout:                *timeout,
	}
}

func assertFlag(flag, name string) {
	if flag == "" {
		log.Fatalf("Missing -%s flag\n", name)
	}
}
<commit_msg>Explain the timeout flag better<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"github.com/cenkalti/backoff"
	"github.com/pivotal-cf/rabbitmq-upgrade-preparation/rabbitmqctl"
	"github.com/pivotal-cf/rabbitmq-upgrade-preparation/versions"
)

func main() {
	logger := log.New(os.Stdout, "", 0)
	log.SetFlags(0)

	args := parseArgs()

	logger.Printf("Checking whether upgrade preparation is necessary for %s\n", args.node)
	rabbitMQCtl := rabbitmqctl.New(args.rabbitmqctlPath)

	backOffStrategy := backoff.NewExponentialBackOff()
	backOffStrategy.MaxElapsedTime = args.timeout
	backOffStrategy.InitialInterval = 100 * time.Millisecond

	var status rabbitmqctl.RabbitMQCtlStatus
	var statusErr error
	var retryCount int

	operation := func() error {
		retryCount++
		logger.Printf("Trying to connect to %s...\n", args.node)
		status, statusErr = rabbitMQCtl.Status(args.node)
		if statusErr != nil {
			err := statusErr.(*rabbitmqctl.Error)

			if err.Status == rabbitmqctl.UnreachableEpmd || err.Status == rabbitmqctl.StoppedRabbitNode {
				logger.Printf("RabbitMQ %s already stopped: %s\n", args.node, err)
				return nil
			}
		}

		if backOffStrategy.NextBackOff() != backoff.Stop {
			logger.Printf("Failed to connect to %s after %d retries, retrying in %s\n", args.node, retryCount, backOffStrategy.NextBackOff())
		}
		return statusErr
	}
	retryErr := backoff.Retry(operation, backOffStrategy)

	if retryErr != nil {
		err := retryErr.(*rabbitmqctl.Error)
		if err.Status == rabbitmqctl.UnreachableHost {
			log.Fatalf("Unable to connect to node %s after %d retries within %v: %s", args.node, retryCount, args.timeout, err)
		}
	}

	deployedRabbitVersion, ok := status.RabbitMQVersion()
	if !ok {
		logger.Printf("Safe to proceed without stopping RabbitMQ %s application, exiting: RabbitMQ application already stopped\n", args.node)
		return
	}

	deployedErlangVersion, _ := status.ErlangVersion()

	differences := []versions.VersionDifference{
		&versions.RabbitVersions{Desired: args.desiredRabbitMQVersion, Deployed: deployedRabbitVersion},
		&versions.ErlangVersions{Desired: args.desiredErlangVersion, Deployed: deployedErlangVersion},
	}

	for _, difference := range differences {
		logger.Printf("%s\n", difference.UpgradeMessage())
		if difference.PreparationRequired() {
			logger.Println("The cluster needs to be taken offline as it cannot run in mixed mode")
			logger.Printf("Stopping RabbitMQ on %s\n", args.node)
			if err := rabbitMQCtl.StopApp(args.node); err != nil {
				log.Fatalf("Failed to stop RabbitMQ on %s: %s", args.node, err)
			}
			return
		}
	}
	logger.Println("Safe to proceed without taking the cluster offline")
}

type Args struct {
	rabbitmqctlPath        string
	node                   string
	desiredRabbitMQVersion string
	desiredErlangVersion   string
	timeout                time.Duration
}

func parseArgs() Args {
	rabbitmqctlPath := flag.String("rabbitmqctl-path", "", "Path to rabbitmqctl")
	node := flag.String("node", "", "RabbitMQ node to prepare")
	newRabbitmqVersion := flag.String("new-rabbitmq-version", "", "Version of RabbitMQ that we are upgrading to")
	newErlangVersion := flag.String("new-erlang-version", "", "Version of Erlang that we are upgrading to")
	timeout := flag.Duration("timeout", 60*time.Second, "Maximum time in seconds to wait for the RabbitMQ node that is being prepared")
	flag.Parse()

	assertFlag(*rabbitmqctlPath, "rabbitmqctl-path")
	assertFlag(*node, "node")
	assertFlag(*newRabbitmqVersion, "new-rabbitmq-version")
	assertFlag(*newErlangVersion, "new-erlang-version")

	return Args{
		rabbitmqctlPath: *rabbitmqctlPath,
		node:            *node,
		desiredRabbitMQVersion: *newRabbitmqVersion,
		desiredErlangVersion:   *newErlangVersion,
		timeout:                *timeout,
	}
}

func assertFlag(flag, name string) {
	if flag == "" {
		log.Fatalf("Missing -%s flag\n", name)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strings"

	"github.com/42wim/matterircd/config"
	irckit "github.com/42wim/matterircd/mm-go-irckit"
	"github.com/google/gops/agent"
	"github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	version = "0.20.0-dev"
	githash string
	logger  *logrus.Entry
	v       *viper.Viper
)

func main() {
	if err := agent.Listen(agent.Options{}); err != nil {
		log.Fatal(err)
	}
	ourlog := logrus.New()
	ourlog.Formatter = &logrus.TextFormatter{FullTimestamp: true}
	logger = ourlog.WithFields(logrus.Fields{"module": "matterircd"})
	config.Logger = logger

	// config related. instantiate a new config.Config to store flags
	flagConfig := flag.String("conf", "matterircd.toml", "config file")

	// bools for showing version/enabling debug
	flag.Bool("version", false, "show version")
	flag.Bool("debug", false, "enable debug logging")

	// bind related cfg
	flag.String("bind", "127.0.0.1:6667", "interface:port to bind to, or a path to bind to a Unix socket.")

	// TLS related cfg
	flag.String("tlsbind", "", "interface:port to bind to. (e.g 127.0.0.1:6697)")
	flag.String("tlsdir", ".", "directory to look for key.pem and cert.pem.")

	// Attempt to load values from the config file
	if _, err := os.Stat(*flagConfig); err == nil {
		v, err = config.LoadConfig(*flagConfig)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		v = viper.New()
	}

	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()
	v.BindPFlags(pflag.CommandLine)

	if v.GetBool("debug") {
		logger.Info("enabling debug")
		ourlog.Level = logrus.DebugLevel
		irckit.SetLogLevel("debug")
	}

	if v.GetBool("trace") {
		logger.Info("enabling trace")
		ourlog.Level = logrus.TraceLevel
		irckit.SetLogLevel("trace")
	}

	if v.GetBool("version") {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}

	irckit.SetLogger(logger)

	logger.Infof("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		logger.Infof("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}

	if v.GetString("tlsbind") != "" {
		go func() {
			logger.Infof("Listening on %s (TLS)", v.GetString("tlsbind"))
			socket := tlsbind()
			defer socket.Close()
			start(socket)
		}()
	}

	// backwards compatible

	if v.GetString("bind") != "" {
		go func() {
			var network string
			if strings.ContainsRune(v.GetString("bind"), os.PathSeparator) {
				network = "unix"
			} else {
				network = "tcp"
			}

			socket, err := net.Listen(network, v.GetString("bind"))
			if err != nil {
				logger.Errorf("Can not listen on %s: %v", v.GetString("bind"), err)
				os.Exit(1)
			}

			logger.Infof("Listening on %s", v.GetString("bind"))

			defer socket.Close()
			start(socket)
		}()
	}

	select {}
}

func tlsbind() net.Listener {
	cert, err := tls.LoadX509KeyPair(v.GetString("tlsdir")+"/cert.pem", v.GetString("tlsdir")+"/key.pem")
	if err != nil {
		logger.Errorf("could not load TLS, incorrect directory? Error: %s", err)
		os.Exit(1)
	}

	tlsConfig := tls.Config{Certificates: []tls.Certificate{cert}}
	listenerTLS, err := tls.Listen("tcp", v.GetString("tlsbind"), &tlsConfig)
	if err != nil {
		logger.Errorf("Can not listen on %s: %v\n", v.GetString("tlsbind"), err)
		os.Exit(1)
	}

	logger.Info("TLS listening on ", v.GetString("tlsbind"))

	return listenerTLS
}

func start(socket net.Listener) {
	for {
		conn, err := socket.Accept()
		if err != nil {
			logger.Errorf("Failed to accept connection: %v", err)
			return
		}

		go func() {
			newsrv := irckit.ServerConfig{Name: "matterircd", Version: version}.Server()

			logger.Infof("New connection: %s", conn.RemoteAddr())

			user := irckit.NewUserBridge(conn, newsrv, v)
			err = newsrv.Connect(user)
			if err != nil {
				logger.Errorf("Failed to join: %v", err)
				return
			}
		}()
	}
}
<commit_msg>Parse flags before loading configfile. Fixes #297<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strings"

	"github.com/42wim/matterircd/config"
	irckit "github.com/42wim/matterircd/mm-go-irckit"
	"github.com/google/gops/agent"
	"github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	version = "0.20.0-dev"
	githash string
	logger  *logrus.Entry
	v       *viper.Viper
)

func main() {
	if err := agent.Listen(agent.Options{}); err != nil {
		log.Fatal(err)
	}
	ourlog := logrus.New()
	ourlog.Formatter = &logrus.TextFormatter{FullTimestamp: true}
	logger = ourlog.WithFields(logrus.Fields{"module": "matterircd"})
	config.Logger = logger

	// config related. instantiate a new config.Config to store flags
	flagConfig := flag.String("conf", "matterircd.toml", "config file")

	// bools for showing version/enabling debug
	flag.Bool("version", false, "show version")
	flag.Bool("debug", false, "enable debug logging")

	// bind related cfg
	flag.String("bind", "127.0.0.1:6667", "interface:port to bind to, or a path to bind to a Unix socket.")

	// TLS related cfg
	flag.String("tlsbind", "", "interface:port to bind to. (e.g 127.0.0.1:6697)")
	flag.String("tlsdir", ".", "directory to look for key.pem and cert.pem.")

	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()

	// Attempt to load values from the config file
	if _, err := os.Stat(*flagConfig); err == nil {
		v, err = config.LoadConfig(*flagConfig)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		v = viper.New()
	}

	v.BindPFlags(pflag.CommandLine)

	if v.GetBool("debug") {
		logger.Info("enabling debug")
		ourlog.Level = logrus.DebugLevel
		irckit.SetLogLevel("debug")
	}

	if v.GetBool("trace") {
		logger.Info("enabling trace")
		ourlog.Level = logrus.TraceLevel
		irckit.SetLogLevel("trace")
	}

	if v.GetBool("version") {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}

	irckit.SetLogger(logger)

	logger.Infof("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		logger.Infof("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}

	if v.GetString("tlsbind") != "" {
		go func() {
			logger.Infof("Listening on %s (TLS)", v.GetString("tlsbind"))
			socket := tlsbind()
			defer socket.Close()
			start(socket)
		}()
	}

	// backwards compatible

	if v.GetString("bind") != "" {
		go func() {
			var network string
			if strings.ContainsRune(v.GetString("bind"), os.PathSeparator) {
				network = "unix"
			} else {
				network = "tcp"
			}

			socket, err := net.Listen(network, v.GetString("bind"))
			if err != nil {
				logger.Errorf("Can not listen on %s: %v", v.GetString("bind"), err)
				os.Exit(1)
			}

			logger.Infof("Listening on %s", v.GetString("bind"))

			defer socket.Close()
			start(socket)
		}()
	}

	select {}
}

func tlsbind() net.Listener {
	cert, err := tls.LoadX509KeyPair(v.GetString("tlsdir")+"/cert.pem", v.GetString("tlsdir")+"/key.pem")
	if err != nil {
		logger.Errorf("could not load TLS, incorrect directory? Error: %s", err)
		os.Exit(1)
	}

	tlsConfig := tls.Config{Certificates: []tls.Certificate{cert}}
	listenerTLS, err := tls.Listen("tcp", v.GetString("tlsbind"), &tlsConfig)
	if err != nil {
		logger.Errorf("Can not listen on %s: %v\n", v.GetString("tlsbind"), err)
		os.Exit(1)
	}

	logger.Info("TLS listening on ", v.GetString("tlsbind"))

	return listenerTLS
}

func start(socket net.Listener) {
	for {
		conn, err := socket.Accept()
		if err != nil {
			logger.Errorf("Failed to accept connection: %v", err)
			return
		}

		go func() {
			newsrv := irckit.ServerConfig{Name: "matterircd", Version: version}.Server()

			logger.Infof("New connection: %s", conn.RemoteAddr())

			user := irckit.NewUserBridge(conn, newsrv, v)
			err = newsrv.Connect(user)
			if err != nil {
				logger.Errorf("Failed to join: %v", err)
				return
			}
		}()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"log"

	"github.com/urfave/cli"
)

var (
	version = "0.0.0"
	build   = "0"
)

func main() {
	app := cli.NewApp()
	app.Name = "slack plugin"
	app.Usage = "slack plugin"
	app.Action = run
	app.Version = fmt.Sprintf("%s+%s", version, build)
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "webhook",
			Usage:  "slack webhook url",
			EnvVar: "SLACK_WEBHOOK,PLUGIN_WEBHOOK",
		},
		cli.StringFlag{
			Name:   "channel",
			Usage:  "slack channel",
			EnvVar: "PLUGIN_CHANNEL",
		},
		cli.StringFlag{
			Name:   "recipient",
			Usage:  "slack recipient",
			EnvVar: "PLUGIN_RECIPIENT",
		},
		cli.StringFlag{
			Name:   "username",
			Usage:  "slack username",
			EnvVar: "PLUGIN_USERNAME",
		},
		cli.StringFlag{
			Name:   "template",
			Usage:  "slack template",
			EnvVar: "PLUGIN_TEMPLATE",
		},
		cli.BoolFlag{
			Name:   "link_names",
			Usage:  "slack link names",
			EnvVar: "PLUGIN_LINK_NAMES",
		},
		cli.StringFlag{
			Name:   "image",
			Usage:  "slack image url",
			EnvVar: "PLUGIN_IMAGE_URL",
		},
		cli.StringFlag{
			Name:   "icon.url",
			Usage:  "slack icon url",
			EnvVar: "PLUGIN_ICON_URL",
		},
		cli.StringFlag{
			Name:   "icon.emoji",
			Usage:  "slack emoji url",
			EnvVar: "PLUGIN_ICON_EMOJI",
		},
		cli.StringFlag{
			Name:   "repo.owner",
			Usage:  "repository owner",
			EnvVar: "DRONE_REPO_OWNER",
		},
		cli.StringFlag{
			Name:   "repo.name",
			Usage:  "repository name",
			EnvVar: "DRONE_REPO_NAME",
		},
		cli.StringFlag{
			Name:   "commit.sha",
			Usage:  "git commit sha",
			EnvVar: "DRONE_COMMIT_SHA",
			Value:  "00000000",
		},
		cli.StringFlag{
			Name:   "commit.ref",
			Value:  "refs/heads/master",
			Usage:  "git commit ref",
			EnvVar: "DRONE_COMMIT_REF",
		},
		cli.StringFlag{
			Name:   "commit.branch",
			Value:  "master",
			Usage:  "git commit branch",
			EnvVar: "DRONE_COMMIT_BRANCH",
		},
		cli.StringFlag{
			Name:   "commit.author",
			Usage:  "git author name",
			EnvVar: "DRONE_COMMIT_AUTHOR",
		},
		cli.StringFlag{
			Name:   "commit.pull",
			Usage:  "git pull request",
			EnvVar: "DRONE_PULL_REQUEST",
		},
		cli.StringFlag{
			Name:   "commit.message",
			Usage:  "commit message",
			EnvVar: "DRONE_COMMIT_MESSAGE",
		},
		cli.StringFlag{
			Name:   "build.event",
			Value:  "push",
			Usage:  "build event",
			EnvVar: "DRONE_BUILD_EVENT",
		},
		cli.IntFlag{
			Name:   "build.number",
			Usage:  "build number",
			EnvVar: "DRONE_BUILD_NUMBER",
		},
		cli.StringFlag{
			Name:   "build.status",
			Usage:  "build status",
			Value:  "success",
			EnvVar: "DRONE_BUILD_STATUS",
		},
		cli.StringFlag{
			Name:   "build.link",
			Usage:  "build link",
			EnvVar: "DRONE_BUILD_LINK",
		},
		cli.Int64Flag{
			Name:   "build.started",
			Usage:  "build started",
			EnvVar: "DRONE_BUILD_STARTED",
		},
		cli.Int64Flag{
			Name:   "build.created",
			Usage:  "build created",
			EnvVar: "DRONE_BUILD_CREATED",
		},
		cli.StringFlag{
			Name:   "build.tag",
			Usage:  "build tag",
			EnvVar: "DRONE_TAG",
		},
		cli.StringFlag{
			Name:   "build.deployTo",
			Usage:  "environment deployed to",
			EnvVar: "DRONE_DEPLOY_TO",
		},
		cli.Int64Flag{
			Name:   "job.started",
			Usage:  "job started",
			EnvVar: "DRONE_JOB_STARTED",
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}

func run(c *cli.Context) error {
	plugin := Plugin{
		Repo: Repo{
			Owner: c.String("repo.owner"),
			Name:  c.String("repo.name"),
		},
		Build: Build{
			Tag:      c.String("build.tag"),
			Number:   c.Int("build.number"),
			Event:    c.String("build.event"),
			Status:   c.String("build.status"),
			Commit:   c.String("commit.sha"),
			Ref:      c.String("commit.ref"),
			Branch:   c.String("commit.branch"),
			Author:   c.String("commit.author"),
			Pull:     c.String("commit.pull"),
			Message:  c.String("commit.message"),
			DeployTo: c.String("build.deployTo"),
			Link:     c.String("build.link"),
			Started:  c.Int64("build.started"),
			Created:  c.Int64("build.created"),
		},
		Job: Job{
			Started: c.Int64("job.started"),
		},
		Config: Config{
			Webhook:   c.String("webhook"),
			Channel:   c.String("channel"),
			Recipient: c.String("recipient"),
			Username:  c.String("username"),
			Template:  c.String("template"),
			ImageURL:  c.String("image"),
			IconURL:   c.String("icon.url"),
			IconEmoji: c.String("icon.emoji"),
			LinkNames: c.Bool("link_names"),
		},
	}

	return plugin.Exec()
}
<commit_msg>Use a dash for parameters<commit_after>package main

import (
	"fmt"
	"os"
	"log"

	"github.com/urfave/cli"
)

var (
	version = "0.0.0"
	build   = "0"
)

func main() {
	app := cli.NewApp()
	app.Name = "slack plugin"
	app.Usage = "slack plugin"
	app.Action = run
	app.Version = fmt.Sprintf("%s+%s", version, build)
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "webhook",
			Usage:  "slack webhook url",
			EnvVar: "SLACK_WEBHOOK,PLUGIN_WEBHOOK",
		},
		cli.StringFlag{
			Name:   "channel",
			Usage:  "slack channel",
			EnvVar: "PLUGIN_CHANNEL",
		},
		cli.StringFlag{
			Name:   "recipient",
			Usage:  "slack recipient",
			EnvVar: "PLUGIN_RECIPIENT",
		},
		cli.StringFlag{
			Name:   "username",
			Usage:  "slack username",
			EnvVar: "PLUGIN_USERNAME",
		},
		cli.StringFlag{
			Name:   "template",
			Usage:  "slack template",
			EnvVar: "PLUGIN_TEMPLATE",
		},
		cli.BoolFlag{
			Name:   "link-names",
			Usage:  "slack link names",
			EnvVar: "PLUGIN_LINK_NAMES",
		},
		cli.StringFlag{
			Name:   "image",
			Usage:  "slack image url",
			EnvVar: "PLUGIN_IMAGE_URL",
		},
		cli.StringFlag{
			Name:   "icon.url",
			Usage:  "slack icon url",
			EnvVar: "PLUGIN_ICON_URL",
		},
		cli.StringFlag{
			Name:   "icon.emoji",
			Usage:  "slack emoji url",
			EnvVar: "PLUGIN_ICON_EMOJI",
		},
		cli.StringFlag{
			Name:   "repo.owner",
			Usage:  "repository owner",
			EnvVar: "DRONE_REPO_OWNER",
		},
		cli.StringFlag{
			Name:   "repo.name",
			Usage:  "repository name",
			EnvVar: "DRONE_REPO_NAME",
		},
		cli.StringFlag{
			Name:   "commit.sha",
			Usage:  "git commit sha",
			EnvVar: "DRONE_COMMIT_SHA",
			Value:  "00000000",
		},
		cli.StringFlag{
			Name:   "commit.ref",
			Value:  "refs/heads/master",
			Usage:  "git commit ref",
			EnvVar: "DRONE_COMMIT_REF",
		},
		cli.StringFlag{
			Name:   "commit.branch",
			Value:  "master",
			Usage:  "git commit branch",
			EnvVar: "DRONE_COMMIT_BRANCH",
		},
		cli.StringFlag{
			Name:   "commit.author",
			Usage:  "git author name",
			EnvVar: "DRONE_COMMIT_AUTHOR",
		},
		cli.StringFlag{
			Name:   "commit.pull",
			Usage:  "git pull request",
			EnvVar: "DRONE_PULL_REQUEST",
		},
		cli.StringFlag{
			Name:   "commit.message",
			Usage:  "commit message",
			EnvVar: "DRONE_COMMIT_MESSAGE",
		},
		cli.StringFlag{
			Name:   "build.event",
			Value:  "push",
			Usage:  "build event",
			EnvVar: "DRONE_BUILD_EVENT",
		},
		cli.IntFlag{
			Name:   "build.number",
			Usage:  "build number",
			EnvVar: "DRONE_BUILD_NUMBER",
		},
		cli.StringFlag{
			Name:   "build.status",
			Usage:  "build status",
			Value:  "success",
			EnvVar: "DRONE_BUILD_STATUS",
		},
		cli.StringFlag{
			Name:   "build.link",
			Usage:  "build link",
			EnvVar: "DRONE_BUILD_LINK",
		},
		cli.Int64Flag{
			Name:   "build.started",
			Usage:  "build started",
			EnvVar: "DRONE_BUILD_STARTED",
		},
		cli.Int64Flag{
			Name:   "build.created",
			Usage:  "build created",
			EnvVar: "DRONE_BUILD_CREATED",
		},
		cli.StringFlag{
			Name:   "build.tag",
			Usage:  "build tag",
			EnvVar: "DRONE_TAG",
		},
		cli.StringFlag{
			Name:   "build.deployTo",
			Usage:  "environment deployed to",
			EnvVar: "DRONE_DEPLOY_TO",
		},
		cli.Int64Flag{
			Name:   "job.started",
			Usage:  "job started",
			EnvVar: "DRONE_JOB_STARTED",
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}

func run(c *cli.Context) error {
	plugin := Plugin{
		Repo: Repo{
			Owner: c.String("repo.owner"),
			Name:  c.String("repo.name"),
		},
		Build: Build{
			Tag:      c.String("build.tag"),
			Number:   c.Int("build.number"),
			Event:    c.String("build.event"),
			Status:   c.String("build.status"),
			Commit:   c.String("commit.sha"),
			Ref:      c.String("commit.ref"),
			Branch:   c.String("commit.branch"),
			Author:   c.String("commit.author"),
			Pull:     c.String("commit.pull"),
			Message:  c.String("commit.message"),
			DeployTo: c.String("build.deployTo"),
			Link:     c.String("build.link"),
			Started:  c.Int64("build.started"),
			Created:  c.Int64("build.created"),
		},
		Job: Job{
			Started: c.Int64("job.started"),
		},
		Config: Config{
			Webhook:   c.String("webhook"),
			Channel:   c.String("channel"),
			Recipient: c.String("recipient"),
			Username:  c.String("username"),
			Template:  c.String("template"),
			ImageURL:  c.String("image"),
			IconURL:   c.String("icon.url"),
			IconEmoji: c.String("icon.emoji"),
			LinkNames: c.Bool("link_names"),
		},
	}

	return plugin.Exec()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	webrtc "github.com/keroserene/go-webrtc"
	"github.com/nobonobo/rtcdc-p2p/datachan"
	"github.com/nobonobo/rtcdc-p2p/signaling"
	"github.com/nobonobo/rtcdc-p2p/signaling/client"
)

var iceServers = []string{"stun:stun.l.google.com:19302"}

// Server ...
type Server struct {
	addr string
	*client.Client
	members map[string]*datachan.Connection
}

// NewServer ...
func NewServer(addr, room, id string) *Server {
	s := new(Server)
	s.addr = addr
	s.Client = client.New(room, id, s.dispatch)
	s.members = map[string]*datachan.Connection{}
	return s
}

// Send ...
func (s *Server) Send(to string, v interface{}) error {
	log.Printf("send: %T to %s\n", v, to)
	m := signaling.New(s.ID(), to, v)
	b, err := json.Marshal(m)
	if err != nil {
		return err
	}
	s.Client.Send(b)
	return nil
}

func (s *Server) dispatch(b []byte) {
	var m *signaling.Message
	if err := json.Unmarshal(b, &m); err != nil {
		log.Println(err)
		return
	}
	if m.Sender == s.ID() {
		return
	}
	if m.To != "" && m.To != s.ID() {
		return
	}
	value, err := m.Get()
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("recv: %T from %s\n", value, m.Sender)
	switch v := value.(type) {
	case *signaling.Request:
		if conn := s.members[m.Sender]; conn != nil {
			conn.Close()
		}
		conn, err := datachan.New(iceServers)
		if err != nil {
			log.Println("datachan new failed:", err)
			delete(s.members, m.Sender)
			return
		}
		conn.OnDataChannel = func(channel *webrtc.DataChannel) {
			go func() {
				conn, err := net.Dial("tcp", s.addr)
				if err != nil {
					log.Println("dial failed:", err)
					return
				}
				defer conn.Close()
				c := datachan.NewConn(channel)
				defer c.Close()
				log.Println("connected:", c)
				go io.Copy(conn, c)
				io.Copy(c, conn)
			}()
		}
		offer, err := conn.Offer()
		if err != nil {
			log.Println("offer failed:", err)
			delete(s.members, m.Sender)
			return
		}
		if err := s.Send(m.Sender, &signaling.Offer{Description: offer.Serialize()}); err != nil {
			log.Println("send failed:", err)
			delete(s.members, m.Sender)
			return
		}
		log.Println("offer completed:", m.Sender)
		s.members[m.Sender] = conn

	case *signaling.Offer:
	case *signaling.Answer:
		conn := s.members[m.Sender]
		if conn == nil {
			log.Println("connection failed:", m.Sender)
			return
		}
		sdp := webrtc.DeserializeSessionDescription(v.Description)
		if sdp == nil {
			log.Println("desirialize sdp failed", v.Description)
			return
		}
		if err := conn.SetRemoteDescription(sdp); err != nil {
			log.Println("answer set failed:", err)
			delete(s.members, m.Sender)
			conn.Close()
			return
		}
		ices := conn.IceCandidates()
		log.Println("ices:", len(ices))
		for _, ice := range ices {
			msg := &signaling.Candidate{
				Candidate:     ice.Candidate,
				SdpMid:        ice.SdpMid,
				SdpMLineIndex: ice.SdpMLineIndex,
			}
			log.Printf("candidate: %q\n", ice.Candidate)
			if err := s.Send(m.Sender, msg); err != nil {
				log.Println(err)
				return
			}
			time.Sleep(100 * time.Microsecond)
		}
	case *signaling.Candidate:
		conn := s.members[m.Sender]
		if conn == nil {
			log.Println("connection failed:", m.Sender)
			return
		}
		ice := webrtc.DeserializeIceCandidate(string(m.Value))
		if err := conn.AddIceCandidate(*ice); err != nil {
			log.Println("add ice failed:", err)
		}
	}
}

// Client ...
type Client struct {
	*client.Client
	conn *datachan.Connection
}

// NewClient ...
func NewClient(room, id string) *Client {
	c := new(Client)
	c.Client = client.New(room, id, c.dispatch)
	return c
}

// Open ...
func (c *Client) Open() (net.Conn, error) {
	con, err := datachan.New(iceServers)
	if err != nil {
		return nil, err
	}
	c.conn = con
	if err := c.Join(); err != nil {
		return nil, err
	}
	defer c.Bye()
	complete := make(chan net.Conn, 1)
	c.conn.OnDataChannel = func(channel *webrtc.DataChannel) {
		complete <- datachan.NewConn(channel)
	}
	c.Start()
	defer c.Stop()
	time.Sleep(time.Second)
	if err := c.Send("", &signaling.Request{}); err != nil {
		return nil, err
	}
	channel := <-complete
	return channel, nil
}

// Close ...
func (c *Client) Close() {

}

// Send ...
func (c *Client) Send(to string, v interface{}) error {
	log.Println("send to:", to, v)
	m := signaling.New(c.ID(), to, v)
	b, err := json.Marshal(m)
	if err != nil {
		return err
	}
	c.Client.Send(b)
	return nil
}

func (c *Client) dispatch(b []byte) {
	var m *signaling.Message
	if err := json.Unmarshal(b, &m); err != nil {
		log.Println(err)
		return
	}
	if m.Sender == c.ID() {
		return
	}
	if m.To != c.ID() {
		return
	}
	value, err := m.Get()
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("recv: %T from %s\n", value, m.Sender)
	switch v := value.(type) {
	case *signaling.Request:
	case *signaling.Offer:
		sdp := webrtc.DeserializeSessionDescription(v.Description)
		if sdp == nil {
			log.Println("desirialize sdp failed", v.Description)
			return
		}
		answer, err := c.conn.Answer(sdp)
		if err != nil {
			log.Println(err)
			return
		}
		if err := c.Send(m.Sender, &signaling.Answer{Description: answer.Serialize()}); err != nil {
			log.Println(err)
			return
		}
		ices := c.conn.IceCandidates()
		log.Println("ices:", len(ices))
		for _, ice := range ices[2:] {
			msg := &signaling.Candidate{
				Candidate:     ice.Candidate,
				SdpMid:        ice.SdpMid,
				SdpMLineIndex: ice.SdpMLineIndex,
			}
			log.Printf("candidate: %q\n", ice.Candidate)
			if err := c.Send(m.Sender, msg); err != nil {
				log.Println(err)
				return
			}
			time.Sleep(100 * time.Microsecond)
		}
	case *signaling.Answer:
	case *signaling.Candidate:
		ice := webrtc.DeserializeIceCandidate(string(m.Value))
		if err := c.conn.AddIceCandidate(*ice); err != nil {
			log.Println(err)
		}
	}
}

func main() {
	var client bool
	var addr, room, id string
	flag.BoolVar(&client, "client", false, "client mode")
	flag.StringVar(&addr, "addr", "127.0.0.1:22", "host:port")
	flag.StringVar(&room, "room", "sample", "name of room")
	flag.StringVar(&id, "id", "**master**", "name of id")
	flag.Parse()
	if id == "" {
		log.Fatalln("id must set unique")
	}
	webrtc.SetLoggingVerbosity(0)
	if client {
		// client mode
		l, err := net.Listen("tcp", addr)
		if err != nil {
			log.Fatalln(err)
		}
		log.Println("listen:", addr)
		for {
			sock, err := l.Accept()
			if err != nil {
				log.Println(err)
				continue
			}
			go func() {
				c := NewClient(room, id)
				conn, err := c.Open()
				if err != nil {
					log.Fatalln(err)
				}
				log.Println("connected:", conn)
				defer c.Close()
				defer conn.Close()
				go io.Copy(conn, sock)
				io.Copy(sock, conn)
			}()
		}
	}
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGINT)
	s := NewServer(addr, room, id)
	go func() {
		defer s.Bye()
		for {
			if err := s.Create(); err != nil {
				log.Println(err)
			}
			time.Sleep(10 * time.Second)
		}
	}()
	s.Start()
	defer s.Stop()
	<-sig
}
<commit_msg>add debug print<commit_after>package main

import (
	"encoding/json"
	"flag"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	webrtc "github.com/keroserene/go-webrtc"
	"github.com/nobonobo/rtcdc-p2p/datachan"
	"github.com/nobonobo/rtcdc-p2p/signaling"
	"github.com/nobonobo/rtcdc-p2p/signaling/client"
)

var iceServers = []string{"stun:stun.l.google.com:19302"}

// Server ...
type Server struct {
	addr string
	*client.Client
	members map[string]*datachan.Connection
}

// NewServer ...
func NewServer(addr, room, id string) *Server {
	s := new(Server)
	s.addr = addr
	s.Client = client.New(room, id, s.dispatch)
	s.members = map[string]*datachan.Connection{}
	return s
}

// Send ...
func (s *Server) Send(to string, v interface{}) error {
	log.Printf("send: %T to %s\n", v, to)
	m := signaling.New(s.ID(), to, v)
	b, err := json.Marshal(m)
	if err != nil {
		return err
	}
	s.Client.Send(b)
	return nil
}

func (s *Server) dispatch(b []byte) {
	var m *signaling.Message
	if err := json.Unmarshal(b, &m); err != nil {
		log.Println(err)
		return
	}
	if m.Sender == s.ID() {
		return
	}
	if m.To != "" && m.To != s.ID() {
		return
	}
	value, err := m.Get()
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("recv: %T from %s\n", value, m.Sender)
	switch v := value.(type) {
	case *signaling.Request:
		if conn := s.members[m.Sender]; conn != nil {
			conn.Close()
		}
		conn, err := datachan.New(iceServers)
		if err != nil {
			log.Println("datachan new failed:", err)
			delete(s.members, m.Sender)
			return
		}
		conn.OnDataChannel = func(channel *webrtc.DataChannel) {
			go func() {
				conn, err := net.Dial("tcp", s.addr)
				if err != nil {
					log.Println("dial failed:", err)
					return
				}
				defer conn.Close()
				c := datachan.NewConn(channel)
				defer c.Close()
				log.Println("connected:", c)
				go func() {
					_, err := io.Copy(conn, c)
					if err != nil {
						log.Println(err)
					}
				}()
				_, err := io.Copy(c, conn)
				if err != nil {
					log.Println(err)
				}
			}()
		}
		offer, err := conn.Offer()
		if err != nil {
			log.Println("offer failed:", err)
			delete(s.members, m.Sender)
			return
		}
		if err := s.Send(m.Sender, &signaling.Offer{Description: offer.Serialize()}); err != nil {
			log.Println("send failed:", err)
			delete(s.members, m.Sender)
			return
		}
		log.Println("offer completed:", m.Sender)
		s.members[m.Sender] = conn

	case *signaling.Offer:
	case *signaling.Answer:
		conn := s.members[m.Sender]
		if conn == nil {
			log.Println("connection failed:", m.Sender)
			return
		}
		sdp := webrtc.DeserializeSessionDescription(v.Description)
		if sdp == nil {
			log.Println("desirialize sdp failed", v.Description)
			return
		}
		if err := conn.SetRemoteDescription(sdp); err != nil {
			log.Println("answer set failed:", err)
			delete(s.members, m.Sender)
			conn.Close()
			return
		}
		ices := conn.IceCandidates()
		log.Println("ices:", len(ices))
		for _, ice := range ices {
			msg := &signaling.Candidate{
				Candidate:     ice.Candidate,
				SdpMid:        ice.SdpMid,
				SdpMLineIndex: ice.SdpMLineIndex,
			}
			log.Printf("candidate: %q\n", ice.Candidate)
			if err := s.Send(m.Sender, msg); err != nil {
				log.Println(err)
				return
			}
			time.Sleep(100 * time.Microsecond)
		}
	case *signaling.Candidate:
		conn := s.members[m.Sender]
		if conn == nil {
			log.Println("connection failed:", m.Sender)
			return
		}
		ice := webrtc.DeserializeIceCandidate(string(m.Value))
		if err := conn.AddIceCandidate(*ice); err != nil {
			log.Println("add ice failed:", err)
		}
	}
}

// Client ...
type Client struct {
	*client.Client
	conn *datachan.Connection
}

// NewClient ...
func NewClient(room, id string) *Client {
	c := new(Client)
	c.Client = client.New(room, id, c.dispatch)
	return c
}

// Open ...
func (c *Client) Open() (net.Conn, error) {
	con, err := datachan.New(iceServers)
	if err != nil {
		return nil, err
	}
	c.conn = con
	if err := c.Join(); err != nil {
		return nil, err
	}
	defer c.Bye()
	complete := make(chan net.Conn, 1)
	c.conn.OnDataChannel = func(channel *webrtc.DataChannel) {
		complete <- datachan.NewConn(channel)
	}
	c.Start()
	defer c.Stop()
	time.Sleep(time.Second)
	if err := c.Send("", &signaling.Request{}); err != nil {
		return nil, err
	}
	channel := <-complete
	return channel, nil
}

// Close ...
func (c *Client) Close() {

}

// Send ...
func (c *Client) Send(to string, v interface{}) error {
	log.Println("send to:", to, v)
	m := signaling.New(c.ID(), to, v)
	b, err := json.Marshal(m)
	if err != nil {
		return err
	}
	c.Client.Send(b)
	return nil
}

func (c *Client) dispatch(b []byte) {
	var m *signaling.Message
	if err := json.Unmarshal(b, &m); err != nil {
		log.Println(err)
		return
	}
	if m.Sender == c.ID() {
		return
	}
	if m.To != c.ID() {
		return
	}
	value, err := m.Get()
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("recv: %T from %s\n", value, m.Sender)
	switch v := value.(type) {
	case *signaling.Request:
	case *signaling.Offer:
		sdp := webrtc.DeserializeSessionDescription(v.Description)
		if sdp == nil {
			log.Println("desirialize sdp failed", v.Description)
			return
		}
		answer, err := c.conn.Answer(sdp)
		if err != nil {
			log.Println(err)
			return
		}
		if err := c.Send(m.Sender, &signaling.Answer{Description: answer.Serialize()}); err != nil {
			log.Println(err)
			return
		}
		ices := c.conn.IceCandidates()
		log.Println("ices:", len(ices))
		for _, ice := range ices[2:] {
			msg := &signaling.Candidate{
				Candidate:     ice.Candidate,
				SdpMid:        ice.SdpMid,
				SdpMLineIndex: ice.SdpMLineIndex,
			}
			log.Printf("candidate: %q\n", ice.Candidate)
			if err := c.Send(m.Sender, msg); err != nil {
				log.Println(err)
				return
			}
			time.Sleep(100 * time.Microsecond)
		}
	case *signaling.Answer:
	case *signaling.Candidate:
		ice := webrtc.DeserializeIceCandidate(string(m.Value))
		if err := c.conn.AddIceCandidate(*ice); err != nil {
			log.Println(err)
		}
	}
}

func main() {
	var client bool
	var addr, room, id string
	flag.BoolVar(&client, "client", false, "client mode")
	flag.StringVar(&addr, "addr", "127.0.0.1:22", "host:port")
	flag.StringVar(&room, "room", "sample", "name of room")
	flag.StringVar(&id, "id", "**master**", "name of id")
	flag.Parse()
	if id == "" {
		log.Fatalln("id must set unique")
	}
	webrtc.SetLoggingVerbosity(0)
	if client {
		// client mode
		l, err := net.Listen("tcp", addr)
		if err != nil {
			log.Fatalln(err)
		}
		log.Println("listen:", addr)
		for {
			sock, err := l.Accept()
			if err != nil {
				log.Println(err)
				continue
			}
			go func() {
				c := NewClient(room, id)
				conn, err := c.Open()
				if err != nil {
					log.Fatalln(err)
				}
				log.Println("connected:", conn)
				defer c.Close()
				defer conn.Close()
				go func() {
					_, err := io.Copy(conn, sock)
					if err != nil {
						log.Println(err)
					}
				}()
				_, err := io.Copy(sock, conn)
				if err != nil {
					log.Println(err)
				}
			}()
		}
	}
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGINT)
	s := NewServer(addr, room, id)
	go func() {
		defer s.Bye()
		for {
			if err := s.Create(); err != nil {
				log.Println(err)
			}
			time.Sleep(10 * time.Second)
		}
	}()
	s.Start()
	defer s.Stop()
	<-sig
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/bjwbell/gensimd/codegen"
	"github.com/bjwbell/gensimd/simd"

	"go/build"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/ssautil"
	"golang.org/x/tools/go/types"
)

func filePath(pathName string) string {
	split := strings.Split(pathName, "/")
	dir := ""
	if len(split) == 1 {
		dir = "."
	} else if len(split) == 2 {
		dir = split[0] + "/"
	} else {
		dir = strings.Join(split[0:len(split)-2], "/")
	}
	return dir
}

func fileName(pathName string) string {
	split := strings.Split(pathName, "/")
	name := ""
	if len(split) == 0 {
		name = ""
	} else {
		name = split[len(split)-1]
	}
	return name
}

func main() {
	var ssaDump = flag.Bool("ssa", false, "dump ssa representation")
	var outputFile = flag.String("o", "", "write Go Assembly to file")
	flag.Parse()
	args := flag.Args()
	file := os.ExpandEnv("$GOFILE")
	funcName := ""
	if len(args) == 1 {
		funcName = args[0]

	} else if len(args) == 2 {
		file = args[0]
		funcName = args[1]
	}
	f, err := simd.ParseFile(file)
	if err != nil {
		msg := "Error parsing file \"%v\", error msg \"%v\""
		log.Fatalf(msg, file, err)
	}

	filePkgName := f.Pkg.Name()
	filePkgPath := f.Pkg.Path()
	conf := loader.Config{Build: &build.Default}

	// Choose types.Sizes from conf.Build.
	var wordSize int64 = 8
	switch conf.Build.GOARCH {
	case "386", "arm":
		panic("SIMD invalid for x86 and arm")
	}
	conf.TypeChecker.Sizes = &types.StdSizes{
		MaxAlign: 8,
		WordSize: wordSize,
	}

	// Use the initial file from the command line/$GOFILE.
	conf.CreateFromFilenames(filePath(file), file)

	// Load, parse and type-check
	iprog, err := conf.Load()
	if err != nil {
		log.Fatalf("conf.Load, error msg \"%v\"", err)
	}

	// Create and build SSA-form program representation.
	builderMode := ssa.SanityCheckFunctions
	if *ssaDump {
		builderMode = ssa.PrintFunctions
	}
	prog := ssautil.CreateProgram(iprog, builderMode)
	if prog == nil {
		log.Fatalf("Couldn't create ssa representation")
	}
	// Build and display only the initial packages (and synthetic wrappers)
	for _, info := range iprog.InitialPackages() {
		prog.Package(info.Pkg).Build()
	}

	opcodefile := "codegen/instructionsetxml/Opcodes/opcodes/x86_64.xml"
	foundpkg := false
	foundfn := false
	for _, pkg := range prog.AllPackages() {
		if pkg.Pkg.Path() == filePkgPath+"/" && pkg.Pkg.Name() == filePkgName {
			foundpkg = true
			if fn := pkg.Func(funcName); fn == nil {
				msg := "Function \"%v\" not found in package \"%v\""
				log.Fatalf(msg, funcName, filePkgName)
			} else {
				foundfn = true
				codegenFn, err := codegen.CreateFunction(opcodefile, fn)
				if err != nil {
					msg := "codegen.CreateFunction,  error msg \"%v\""
					log.Fatalf(msg, err)
				}
				if asm, err := codegenFn.GoAssembly(); err != nil {
					msg := "Error creating fn asm, error msg \"%v\"\n"
					log.Fatalf(msg, err)
				} else {
					if *outputFile == "" {
						fmt.Println(asm)
					} else {
						writeFile(*outputFile, asm)
					}
				}
			}
		}
	}
	if !foundpkg {
		msg := "Didn't find package, \"%v\", for function \"%v\""
		log.Fatalf(msg, filePkgName, funcName)

	} else if foundpkg && !foundfn {
		msg := "Didn't find function, \"%v\", in package \"%v\""
		log.Fatalf(msg, funcName, filePkgName)
	}
}

func writeFile(filename, contents string) {
	if err := ioutil.WriteFile(filename, []byte(contents), 0644); err != nil {
		log.Fatalf("Error writing to file, error msg \"%v\"\n", err)
	}
}
<commit_msg>Add file name flag, "file", and function name flag, "fnname".<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"

	"github.com/bjwbell/gensimd/codegen"
	"github.com/bjwbell/gensimd/simd"

	"go/build"

	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/ssautil"
	"golang.org/x/tools/go/types"
)

func filePath(pathName string) string {
	split := strings.Split(pathName, "/")
	dir := ""
	if len(split) == 1 {
		dir = "."
	} else if len(split) == 2 {
		dir = split[0] + "/"
	} else {
		dir = strings.Join(split[0:len(split)-2], "/")
	}
	return dir
}

func fileName(pathName string) string {
	split := strings.Split(pathName, "/")
	name := ""
	if len(split) == 0 {
		name = ""
	} else {
		name = split[len(split)-1]
	}
	return name
}

func main() {
	var ssaDump = flag.Bool("ssa", false, "dump ssa representation")
	var outputFile = flag.String("o", "", "write Go Assembly to file")
	var inputFile = flag.String("file", "", "input file")
	var fnname = flag.String("fnname", "", "function name")
	flag.Parse()
	file := os.ExpandEnv("$GOFILE")
	if *inputFile != "" {
		file = *inputFile
	}
	f, err := simd.ParseFile(file)
	if err != nil {
		msg := "Error parsing file \"%v\", error msg \"%v\""
		log.Fatalf(msg, file, err)
	}

	filePkgName := f.Pkg.Name()
	filePkgPath := f.Pkg.Path()
	conf := loader.Config{Build: &build.Default}

	// Choose types.Sizes from conf.Build.
	var wordSize int64 = 8
	switch conf.Build.GOARCH {
	case "386", "arm":
		panic("SIMD invalid for x86 and arm")
	}
	conf.TypeChecker.Sizes = &types.StdSizes{
		MaxAlign: 8,
		WordSize: wordSize,
	}

	// Use the initial file from the command line/$GOFILE.
	conf.CreateFromFilenames(filePath(file), file)

	// Load, parse and type-check
	iprog, err := conf.Load()
	if err != nil {
		log.Fatalf("conf.Load, error msg \"%v\"", err)
	}

	// Create and build SSA-form program representation.
	builderMode := ssa.SanityCheckFunctions
	if *ssaDump {
		builderMode = ssa.PrintFunctions
	}
	prog := ssautil.CreateProgram(iprog, builderMode)
	if prog == nil {
		log.Fatalf("Couldn't create ssa representation")
	}
	// Build and display only the initial packages (and synthetic wrappers)
	for _, info := range iprog.InitialPackages() {
		prog.Package(info.Pkg).Build()
	}

	opcodefile := "codegen/instructionsetxml/Opcodes/opcodes/x86_64.xml"
	foundpkg := false
	foundfn := false
	for _, pkg := range prog.AllPackages() {
		if pkg.Pkg.Path() == filePkgPath+"/" && pkg.Pkg.Name() == filePkgName {
			foundpkg = true
			if fn := pkg.Func(*fnname); fn == nil {
				msg := "Function \"%v\" not found in package \"%v\""
				log.Fatalf(msg, fnname, filePkgName)
			} else {
				foundfn = true
				codegenFn, err := codegen.CreateFunction(opcodefile, fn)
				if err != nil {
					msg := "codegen.CreateFunction,  error msg \"%v\""
					log.Fatalf(msg, err)
				}
				if asm, err := codegenFn.GoAssembly(); err != nil {
					msg := "Error creating fn asm, error msg \"%v\"\n"
					log.Fatalf(msg, err)
				} else {
					if *outputFile == "" {
						fmt.Println(asm)
					} else {
						writeFile(*outputFile, asm)
					}
				}
			}
		}
	}
	if !foundpkg {
		msg := "Didn't find package, \"%v\", for function \"%v\""
		log.Fatalf(msg, filePkgName, fnname)

	} else if foundpkg && !foundfn {
		msg := "Didn't find function, \"%v\", in package \"%v\""
		log.Fatalf(msg, fnname, filePkgName)
	}
}

func writeFile(filename, contents string) {
	if err := ioutil.WriteFile(filename, []byte(contents), 0644); err != nil {
		log.Fatalf("Error writing to file, error msg \"%v\"\n", err)
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gorilla/mux"
	"github.com/mfine30/prodda/timer"
)

var (
	travisToken string
)

func main() {
	port := os.Getenv("PORT")
	travisToken = os.Getenv("TRAVIS_TOKEN")

	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/", homeHandler)
	prods := r.Path("/prods").Subrouter()
	prods.Methods("POST").HandlerFunc(prodsCreateHandler)

	log.Fatal(http.ListenAndServe(":"+port, r))
}

func homeHandler(rw http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(rw, "Prodda")
}

func prodsCreateHandler(rw http.ResponseWriter, r *http.Request) {
	dingAt := time.Now().Add(5 * time.Second)
	task := timer.NewTravisTask(travisToken)
	alarm, err := timer.NewAlarm(dingAt, task)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Alarm created\n")

	go alarm.Start()

	fmt.Fprintln(rw, "New prod created")
}
<commit_msg>Parse trigger time in RFC3339 format when creating new prod.<commit_after>package main

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

	"github.com/gorilla/mux"
	"github.com/mfine30/prodda/timer"
)

var (
	travisToken string
)

func main() {
	port := os.Getenv("PORT")
	travisToken = os.Getenv("TRAVIS_TOKEN")

	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/", homeHandler)
	prods := r.Path("/prods").Subrouter()
	prods.Methods("POST").HandlerFunc(prodsCreateHandler)

	log.Fatal(http.ListenAndServe(":"+port, r))
}

func homeHandler(rw http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(rw, "Prodda")
}

func prodsCreateHandler(rw http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	fmt.Printf("Query: %+v\n", query)
	timeQuery := query["time"]
	if timeQuery == nil {
		log.Println("Time not present in URL params")
		fmt.Fprintln(rw, "ERROR: time must be present in URL params")
		return
	}

	fmt.Printf("time-now: %v\n", time.Now().Format(time.RFC3339))
	fmt.Printf("time [0]: %s\n", timeQuery[0])
	t, err := time.Parse(time.RFC3339, timeQuery[0])
	if err != nil {
		log.Printf("Cannot parse time from %+v\n", timeQuery[0])
		fmt.Fprintf(rw, "ERROR: Cannot parse time from %+s\n", timeQuery[0])
		return
	}

	task := timer.NewTravisTask(travisToken)
	alarm, err := timer.NewAlarm(t, task)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Alarm created\n")

	go alarm.Start()

	fmt.Fprintln(rw, "New prod created")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
)

const (
	usage = `
Usage: curl http://127.0.0.1:8080/[endpoint]

    Perform HTTP request against the API for a specific action.

Endpoints:

    /            show this message
    /cowsay      talking cow
    /health      check health status
    /hostname    display hostname
`

	cowsay = `
 _______________________________________
|  You are only young once, but you can |
|  stay immature indefinitely.          |
 ---------------------------------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||
`
)

type Payload struct {
	Message string `json:"message"`
}

func endpointHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", usage)
	log.Printf("%s", r.URL.Path)
}

func hostnameHandler(w http.ResponseWriter, r *http.Request) {
	hostname, _ := os.Hostname()
	fmt.Fprintf(w, "Hostname: %s\n", hostname)
	log.Printf("%s", r.URL.Path)
}

func cowsayHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", cowsay)
	log.Printf("%s", r.URL.Path)

}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK")
	log.Printf("%s", r.URL.Path)
}

func logMessage(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json")

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()

	var msg Payload
	err := decoder.Decode(&msg)
	if err != nil {
		http.Error(w, "error: reading request body", http.StatusInternalServerError)
	}

	fmt.Fprint(w, msg.Message)
	fmt.Println(msg.Message)
}

func main() {

	router := mux.NewRouter()

	router.HandleFunc("/", endpointHandler).Methods("GET")
	router.HandleFunc("/cowsay", cowsayHandler).Methods("GET")
	router.HandleFunc("/health", healthCheckHandler).Methods("GET")
	router.HandleFunc("/hostname", hostnameHandler).Methods("GET")
	router.HandleFunc("/log", logMessage).Methods("POST")

	log.Fatal(http.ListenAndServe(":8080", router))

}
<commit_msg>health: do not log health endpoint<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/gorilla/mux"
)

const (
	usage = `
Usage: curl http://127.0.0.1:8080/[endpoint]

    Perform HTTP request against the API for a specific action.

Endpoints:

    /            show this message
    /cowsay      talking cow
    /health      check health status
    /hostname    display hostname
`

	cowsay = `
 _______________________________________
|  You are only young once, but you can |
|  stay immature indefinitely.          |
 ---------------------------------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||
`
)

type Payload struct {
	Message string `json:"message"`
}

func endpointHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", usage)
	log.Printf("%s", r.URL.Path)
}

func hostnameHandler(w http.ResponseWriter, r *http.Request) {
	hostname, _ := os.Hostname()
	fmt.Fprintf(w, "Hostname: %s\n", hostname)
	log.Printf("%s", r.URL.Path)
}

func cowsayHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "%s", cowsay)
	log.Printf("%s", r.URL.Path)

}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "OK")
}

func logMessage(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json")

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()

	var msg Payload
	err := decoder.Decode(&msg)
	if err != nil {
		http.Error(w, "error: reading request body", http.StatusInternalServerError)
	}

	fmt.Fprint(w, msg.Message)
	fmt.Println(msg.Message)
}

func main() {

	router := mux.NewRouter()

	router.HandleFunc("/", endpointHandler).Methods("GET")
	router.HandleFunc("/cowsay", cowsayHandler).Methods("GET")
	router.HandleFunc("/health", healthCheckHandler).Methods("GET")
	router.HandleFunc("/hostname", hostnameHandler).Methods("GET")
	router.HandleFunc("/log", logMessage).Methods("POST")

	log.Fatal(http.ListenAndServe(":8080", router))

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"

	"github.com/jagregory/cfval/reporting"
	"github.com/mitchellh/cli"
)

var forgiving = flag.Bool("forgiving", false, "Ignore unrecognised resources")

type ByContext reporting.Reports

func (a ByContext) Len() int           { return len(a) }
func (a ByContext) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByContext) Less(i, j int) bool { return a[i].ContextReadable < a[j].ContextReadable }

var ui = &cli.ColoredUi{
	InfoColor:  cli.UiColorNone,
	ErrorColor: cli.UiColorRed,
	WarnColor:  cli.UiColorYellow,
	Ui: &cli.BasicUi{
		Reader:      os.Stdin,
		Writer:      os.Stdout,
		ErrorWriter: os.Stderr,
	},
}

func printReports(reports reporting.Reports) {
	sort.Sort(ByContext(reports))

	maxLength := 0
	for _, report := range reports {
		context := report.ContextReadable
		if len(context) > maxLength {
			maxLength = len(context)
		}
	}

	for _, report := range reports {
		context := report.ContextReadable

		str := context
		str += " "
		for i := 0; i < maxLength-len(context); i++ {
			str += "."
		}
		str += "... "
		str += report.Message

		if report.Level == reporting.Failure {
			ui.Error(str)
		} else if report.Level == reporting.Warning {
			ui.Warn(str)
		} else {
			ui.Info(str)
		}
	}
}

func printSummary(stats reporting.Stats) {
	fmt.Printf("%d failures\n", stats.Failures)
}

func getReadStream(args []string) (io.Reader, error) {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) == 0 {
		return os.Stdin, nil
	} else if len(args) > 0 {
		return os.Open(args[0])
	} else {
		return nil, fmt.Errorf("Provide either a filename or pipe something")
	}
}

type ValidateCommand struct{}

func (ValidateCommand) Help() string {
	return `
Usage: cfval validate [filename]
       cat filename | cfval validate

  Given a CloudFormation JSON template, validate will parse and execute various
  tests against the template. Any problems will be printed and a non-zero exit
  code reported.

Options:

  -warnings-as-errors    Treat warnings as errors
`
}

func (ValidateCommand) Synopsis() string {
	return "Validate a CloudFormation template"
}

func (c ValidateCommand) Run(args []string) int {
	var warningsAsErrors bool

	cmdFlags := flag.NewFlagSet("validate", flag.ContinueOnError)
	cmdFlags.BoolVar(&warningsAsErrors, "warnings-as-errors", false, "warnings-as-errors")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) == 0 {
		return cli.RunResultHelp
	}

	stream, err := getReadStream(args)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	bytes, err := ioutil.ReadAll(stream)
	if err != nil {
		fmt.Println("Error reading JSON from Stdin")
		return 1
	}

	template, err := parseTemplateJSON(bytes, *forgiving)
	if err != nil {
		fmt.Println("Error parsing JSON:", err)
		return 1
	}

	fmt.Println(warningsAsErrors)

	if ok, reports := template.Validate(); !ok {
		stats := reports.Stats()

		printReports(reports)
		fmt.Println()
		printSummary(stats)

		if warningsAsErrors || stats.Failures > 0 {
			return 1
		}
	}

	return 0
}

func main() {
	app := cli.NewCLI("cfval", "0.1.0")
	app.Args = os.Args[1:]
	app.Commands = map[string]cli.CommandFactory{
		"validate": func() (cli.Command, error) {
			return ValidateCommand{}, nil
		},
	}

	exitStatus, err := app.Run()
	if err != nil {
		log.Println(err)
	}

	os.Exit(exitStatus)
}
<commit_msg>Include warnings in summary<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"

	"github.com/jagregory/cfval/reporting"
	"github.com/mitchellh/cli"
)

var forgiving = flag.Bool("forgiving", false, "Ignore unrecognised resources")

type ByContext reporting.Reports

func (a ByContext) Len() int           { return len(a) }
func (a ByContext) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByContext) Less(i, j int) bool { return a[i].ContextReadable < a[j].ContextReadable }

var ui = &cli.ColoredUi{
	InfoColor:  cli.UiColorNone,
	ErrorColor: cli.UiColorRed,
	WarnColor:  cli.UiColorYellow,
	Ui: &cli.BasicUi{
		Reader:      os.Stdin,
		Writer:      os.Stdout,
		ErrorWriter: os.Stderr,
	},
}

func printReports(reports reporting.Reports) {
	sort.Sort(ByContext(reports))

	maxLength := 0
	for _, report := range reports {
		context := report.ContextReadable
		if len(context) > maxLength {
			maxLength = len(context)
		}
	}

	for _, report := range reports {
		context := report.ContextReadable

		str := context
		str += " "
		for i := 0; i < maxLength-len(context); i++ {
			str += "."
		}
		str += "... "
		str += report.Message

		if report.Level == reporting.Failure {
			ui.Error(str)
		} else if report.Level == reporting.Warning {
			ui.Warn(str)
		} else {
			ui.Info(str)
		}
	}
}

func printSummary(stats reporting.Stats) {
	fmt.Printf("%d failures, %d warnings\n", stats.Failures, stats.Warnings)
}

func getReadStream(args []string) (io.Reader, error) {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) == 0 {
		return os.Stdin, nil
	} else if len(args) > 0 {
		return os.Open(args[0])
	} else {
		return nil, fmt.Errorf("Provide either a filename or pipe something")
	}
}

type ValidateCommand struct{}

func (ValidateCommand) Help() string {
	return `
Usage: cfval validate [filename]
       cat filename | cfval validate

  Given a CloudFormation JSON template, validate will parse and execute various
  tests against the template. Any problems will be printed and a non-zero exit
  code reported.

Options:

  -warnings-as-errors    Treat warnings as errors
`
}

func (ValidateCommand) Synopsis() string {
	return "Validate a CloudFormation template"
}

func (c ValidateCommand) Run(args []string) int {
	var warningsAsErrors bool

	cmdFlags := flag.NewFlagSet("validate", flag.ContinueOnError)
	cmdFlags.BoolVar(&warningsAsErrors, "warnings-as-errors", false, "warnings-as-errors")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) == 0 {
		return cli.RunResultHelp
	}

	stream, err := getReadStream(args)
	if err != nil {
		fmt.Println(err)
		return 1
	}

	bytes, err := ioutil.ReadAll(stream)
	if err != nil {
		fmt.Println("Error reading JSON from Stdin")
		return 1
	}

	template, err := parseTemplateJSON(bytes, *forgiving)
	if err != nil {
		fmt.Println("Error parsing JSON:", err)
		return 1
	}

	fmt.Println(warningsAsErrors)

	if ok, reports := template.Validate(); !ok {
		stats := reports.Stats()

		printReports(reports)
		fmt.Println()
		printSummary(stats)

		if warningsAsErrors || stats.Failures > 0 {
			return 1
		}
	}

	return 0
}

func main() {
	app := cli.NewCLI("cfval", "0.1.0")
	app.Args = os.Args[1:]
	app.Commands = map[string]cli.CommandFactory{
		"validate": func() (cli.Command, error) {
			return ValidateCommand{}, nil
		},
	}

	exitStatus, err := app.Run()
	if err != nil {
		log.Println(err)
	}

	os.Exit(exitStatus)
}
<|endoftext|>


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

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client
var PetDB *Pets

func main() {
	strID := os.Getenv("ChannelID")
	numID, err := strconv.ParseInt(strID, 10, 64)
	if err != nil {
		log.Fatal("Wrong environment setting about ChannelID")
	}

	PetDB = NewPets()
	bot, err = linebot.NewClient(numID, os.Getenv("ChannelSecret"), os.Getenv("MID"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	received, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, result := range received.Results {
		content := result.Content()

		//Log detail receive content
		if content != nil {
			log.Println("RECEIVE Msg:", content.IsMessage, " OP:", content.IsOperation, " type:", content.ContentType, " from:", content.From, "to:", content.To, " ID:", content.ID)
		}
		//Add with new friend.
		if content != nil && content.IsOperation {
			opContent, err := content.OperationContent()
			if err != nil {
				log.Println("OP retreival error:", err)
			} else {
				log.Println("OP detail from:", opContent.From, " ID:", opContent.ID, " TO:", opContent.To)
				log.Println("OP rawdata:", result.RawContent, " from:", result.RawContent.From, " to:", result.RawContent.To, " id:", result.RawContent.ID)
			}

			out := fmt.Sprintf("您好，感謝你加入成為好友一起幫助流浪動物找到新的家．輸入任何文字後，會隨機得到一個流浪動物，你可以不斷重複輸入文字然後查看目前所有的流浪動物．")
			_, err = bot.SendText(result.RawContent.To, out)
			if err != nil {
				log.Println(err)
			}
			log.Println("New friend add, send cue to new friend.")
		}

		if content != nil && content.IsMessage && content.ContentType == linebot.ContentTypeText {

			pet := PetDB.GetNextPet()
			out := fmt.Sprintf("您好，目前的動物：名為%s, 所在地為:%s, 敘述: %s 電話為:%s", pet.Name, pet.Resettlement, pet.Note, pet.Phone)

			// text, err := content.TextContent()
			_, err = bot.SendText([]string{content.From}, out)
			if err != nil {
				log.Println(err)
			}

			_, err = bot.SendImage([]string{content.From}, pet.ImageName, pet.ImageName)
			if err != nil {
				log.Println(err)
			}

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

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client
var PetDB *Pets

func main() {
	strID := os.Getenv("ChannelID")
	numID, err := strconv.ParseInt(strID, 10, 64)
	if err != nil {
		log.Fatal("Wrong environment setting about ChannelID")
	}

	PetDB = NewPets()
	bot, err = linebot.NewClient(numID, os.Getenv("ChannelSecret"), os.Getenv("MID"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	received, err := bot.ParseRequest(r)
	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}
	for _, result := range received.Results {
		content := result.Content()

		//Log detail receive content
		if content != nil {
			log.Println("RECEIVE Msg:", content.IsMessage, " OP:", content.IsOperation, " type:", content.ContentType, " from:", content.From, "to:", content.To, " ID:", content.ID)
		}
		//Add with new friend.
		if content != nil && content.IsOperation {
			opContent, err := content.OperationContent()
			if err != nil {
				log.Println("OP retreival error:", err)
			} else {
				log.Println("OP detail from:", opContent.From, " ID:", opContent.ID, " TO:", opContent.To)
				log.Println("OP rawdata:", result.RawContent, " from:", result.RawContent.From, " to:", result.RawContent.To, " id:", result.RawContent.ID, " param:", result.RawContent.Params)
			}

			out := fmt.Sprintf("您好，感謝你加入成為好友一起幫助流浪動物找到新的家．輸入任何文字後，會隨機得到一個流浪動物，你可以不斷重複輸入文字然後查看目前所有的流浪動物．")
			_, err = bot.SendText(result.RawContent.Params, out)
			if err != nil {
				log.Println(err)
			}
			log.Println("New friend add, send cue to new friend.")
		}

		if content != nil && content.IsMessage && content.ContentType == linebot.ContentTypeText {

			pet := PetDB.GetNextPet()
			out := fmt.Sprintf("您好，目前的動物：名為%s, 所在地為:%s, 敘述: %s 電話為:%s", pet.Name, pet.Resettlement, pet.Note, pet.Phone)

			// text, err := content.TextContent()
			_, err = bot.SendText([]string{content.From}, out)
			if err != nil {
				log.Println(err)
			}

			_, err = bot.SendImage([]string{content.From}, pet.ImageName, pet.ImageName)
			if err != nil {
				log.Println(err)
			}

		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/render"
	"github.com/xyproto/auth"
	"github.com/xyproto/fizz"
	"github.com/xyproto/instapage"
)

const (
	Version       = "1.0"
	API           = "/api/" + Version + "/"
	Title         = "Score Server " + Version
	AdminUsername = "admin"
)

type RegisterAdmin struct {
	Password1 string `form:"password1" binding:"required"`
	Password2 string `form:"password2" binding:"required"`
	Email     string `form:"email" binding:"required"`
}

type LoginAdmin struct {
	Password string `form:"password" binding:"required"`
}

func main() {
	fmt.Println(Title)

	// New Martini
	m := martini.Classic()

	// New Renderer
	r := render.Renderer(render.Options{})
	m.Use(r)

	// Initiate the user and permission system
	fizz := fizz.NewWithRedisConf(7, "")
	userstate := fizz.UserState()

	// Permission system
	//perm := fizz.Perm()

	// Authorization is proviced by http basic auth.
	//perm.Clear()

	// --- Public pages and admin panel ---

	// Public page
	m.Get("/", func(r render.Render) {
		msg := "Everything is fine."
		if !userstate.HasUser(AdminUsername) {
			msg = "No registered administrator. Please visit /register."
		}
		data := map[string]string{
			"title": Title,
			"msg":   msg,
		}

		// Uses templates/index.tmpl
		r.HTML(http.StatusOK, "index", data)
	})

	// Admin status
	// TODO Consider adding a bool2yesno function and use fmt.Sprintf instead
	m.Any("/status", func(r render.Render) {
		s := "has administrator: "
		if userstate.HasUser(AdminUsername) {
			s += "yes"
		} else {
			s += "no"
		}
		s += ", "
		s += "logged in: "
		if userstate.IsLoggedIn(AdminUsername) {
			s += "yes"
		} else {
			s += "no"
		}

		data := map[string]string{
			"title": Title,
			"msg":   s,
		}

		// Uses templates/index.tmpl
		r.HTML(http.StatusOK, "index", data)
	})

	// The admin panel
	m.Get("/admin", func(w http.ResponseWriter, req *http.Request, r render.Render) {
		// TODO: Write a nice admin panel, for managing users, like in ftls2

		data := map[string]string{
			"title": Title,
			"msg":   "Admin panel, work in progress",
		}

		// Uses templates/index.tmpl
		r.HTML(http.StatusOK, "index", data)
	})

	// Enable temporarily for removing and re-creating the admin user with a new pasword
	//m.Get("/remove", func() string {
	//	userstate.RemoveUser(AdminUsername)
	//	return "removed admin user"
	//})

	// --- Admin user management ---

	// Register the admin password
	m.Get("/register", func(w http.ResponseWriter, req *http.Request) {
		// TODO: Handle things differently if a regular user is logged in
		if !userstate.HasUser(AdminUsername) {
			w.Header().Add("Content-Type", "text/html")
			fmt.Fprint(w, "<!doctype html>")
			fmt.Fprint(w, instapage.RegisterForm())
			fmt.Fprint(w, "")
			return
		}
	})
	m.Post("/register", binding.Bind(RegisterAdmin{}), func(ra RegisterAdmin) string {
		username := AdminUsername
		if !userstate.HasUser(username) {
			userstate.AddUser(username, ra.Password1, ra.Email)
			userstate.SetAdminStatus(username)
		}
		return "registered " + username
	})

	// Login admin
	m.Get("/login", func(w http.ResponseWriter, req *http.Request) {
		// TODO: Handle things differently if a regular user is logged in
		if !userstate.AdminRights(req) {
			w.Header().Add("Content-Type", "text/html")
			fmt.Fprint(w, "<!doctype html>")
			fmt.Fprint(w, instapage.LoginForm())
			fmt.Fprint(w, "")
			return
		}
	})
	m.Post("/login", binding.Bind(LoginAdmin{}), func(la LoginAdmin) string {
		username := AdminUsername
		if !userstate.HasUser(username) {
			return "FAIL must have " + username
		}
		if !userstate.CorrectPassword(username, la.Password) {
			return "FAIL password"
		}
		userstate.SetLoggedIn(username)
		return "logged in " + username
	})

	// Logout admin
	m.Any("/logout", func() string {
		username := AdminUsername
		userstate.Logout(username)
		// TODO errorcheck
		return "logged out " + username
	})

	// --- REST methods ---

	// The API uses HTTP Basic Auth instead of cookies
	//perm.AddPublicPath(API)

	// For testing the API
	m.Any(API, func(r render.Render) {
		r.JSON(http.StatusOK, map[string]interface{}{"hello": "fjaselus"})
	})

	// For adding users
	m.Post(API+"create/:username/:password", func(params martini.Params, r render.Render) {
		username := params["username"]
		password := params["password"]
		if userstate.HasUser(username) {
			r.JSON(http.StatusConflict, map[string]interface{}{"error": "user " + username + " already exists"})
			return
		}
		userstate.AddUser(username, password, "")
		if userstate.HasUser(username) {
			r.JSON(http.StatusOK, map[string]interface{}{"create": true})
		} else {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "user " + username + " was not created"})
		}
	})

	// For logging in
	m.Post(API+"login/:username/:password", func(w http.ResponseWriter, params martini.Params, r render.Render) {
		username := params["username"]
		password := params["password"]
		if userstate.CorrectPassword(username, password) {
			userstate.SetLoggedIn(username)

		}
		if !userstate.IsLoggedIn(username) {
			r.JSON(http.StatusUnauthorized, map[string]interface{}{"error": "could not log in " + username})
			return
		}
		r.JSON(http.StatusOK, map[string]interface{}{"login": true})
	})

	// For logging out
	m.Any(API+"logout/:username", func(params martini.Params, r render.Render) {
		username := params["username"]
		userstate.Logout(username)
		if userstate.IsLoggedIn(username) {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "user " + username + " is still logged in!"})
			return
		}
		r.JSON(http.StatusOK, map[string]interface{}{"logout": true})
	})

	// For login status
	m.Any(API+"status/:username", func(params martini.Params, r render.Render) {
		username := params["username"]
		if userstate.IsLoggedIn(username) {
			r.JSON(http.StatusOK, map[string]interface{}{"login": true})
		} else {
			r.JSON(http.StatusOK, map[string]interface{}{"login": "false"})
		}
	})

	// Score POST og GET + timestamp
	m.Post(API+"score/:username/:score", func(params martini.Params, r render.Render) {
		username := params["username"]
		score := params["score"]

		if !userstate.HasUser(username) {
			r.JSON(http.StatusNotFound, map[string]interface{}{"error": "no such user " + username})
			return
		}

		users := userstate.GetUsers()
		users.Set(username, "score", score)

		r.JSON(http.StatusOK, map[string]interface{}{"score set": true})
	})
	m.Get(API+"score/:username", func(params martini.Params, r render.Render) {
		username := params["username"]

		if !userstate.HasUser(username) {
			r.JSON(http.StatusNotFound, map[string]interface{}{"error": "no such user " + username})
			return
		}

		users := userstate.GetUsers()
		score, err := users.Get(username, "score")
		if err != nil {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "could not get score for " + username})
			return
		}

		r.JSON(http.StatusOK, map[string]interface{}{"score": score})
	})

	// Activate the permission middleware
	//m.Use(fizz.All())

	// Share the files in static
	m.Use(martini.Static("static"))

	// Only enable HTTP Basic Auth for paths that starts with "/api"
	m.Use(auth.BasicFunc(func(username, password string) bool {
		// Check if the admin user has the correct password, as registered for the admin user
		return auth.SecureCompare(AdminUsername, username) && userstate.CorrectPassword(AdminUsername, password)
	}, "/api"))

	m.Run() // port 3000 by default
}
<commit_msg>Now create only takes a username<commit_after>package main

import (
	"fmt"
	"net/http"

	"github.com/go-martini/martini"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/render"
	"github.com/xyproto/auth"
	"github.com/xyproto/fizz"
	"github.com/xyproto/instapage"
)

const (
	Version       = "1.0"
	API           = "/api/" + Version + "/"
	Title         = "Score Server " + Version
	AdminUsername = "admin"
)

type RegisterAdmin struct {
	Password1 string `form:"password1" binding:"required"`
	Password2 string `form:"password2" binding:"required"`
	Email     string `form:"email" binding:"required"`
}

type LoginAdmin struct {
	Password string `form:"password" binding:"required"`
}

func main() {
	fmt.Println(Title)

	// New Martini
	m := martini.Classic()

	// New Renderer
	r := render.Renderer(render.Options{})
	m.Use(r)

	// Initiate the user and permission system
	fizz := fizz.NewWithRedisConf(7, "")
	userstate := fizz.UserState()

	// Permission system
	//perm := fizz.Perm()

	// Authorization is proviced by http basic auth.
	//perm.Clear()

	// --- Public pages and admin panel ---

	// Public page
	m.Get("/", func(r render.Render) {
		msg := "Everything is fine."
		if !userstate.HasUser(AdminUsername) {
			msg = "No registered administrator. Please visit /register."
		}
		data := map[string]string{
			"title": Title,
			"msg":   msg,
		}

		// Uses templates/index.tmpl
		r.HTML(http.StatusOK, "index", data)
	})

	// Admin status
	// TODO Consider adding a bool2yesno function and use fmt.Sprintf instead
	m.Any("/status", func(r render.Render) {
		s := "has administrator: "
		if userstate.HasUser(AdminUsername) {
			s += "yes"
		} else {
			s += "no"
		}
		s += ", "
		s += "logged in: "
		if userstate.IsLoggedIn(AdminUsername) {
			s += "yes"
		} else {
			s += "no"
		}

		data := map[string]string{
			"title": Title,
			"msg":   s,
		}

		// Uses templates/index.tmpl
		r.HTML(http.StatusOK, "index", data)
	})

	// The admin panel
	m.Get("/admin", func(w http.ResponseWriter, req *http.Request, r render.Render) {
		// TODO: Write a nice admin panel, for managing users, like in ftls2

		data := map[string]string{
			"title": Title,
			"msg":   "Admin panel, work in progress",
		}

		// Uses templates/index.tmpl
		r.HTML(http.StatusOK, "index", data)
	})

	// Enable temporarily for removing and re-creating the admin user with a new pasword
	//m.Get("/remove", func() string {
	//	userstate.RemoveUser(AdminUsername)
	//	return "removed admin user"
	//})

	// --- Admin user management ---

	// Register the admin password
	m.Get("/register", func(w http.ResponseWriter, req *http.Request) {
		// TODO: Handle things differently if a regular user is logged in
		if !userstate.HasUser(AdminUsername) {
			w.Header().Add("Content-Type", "text/html")
			fmt.Fprint(w, "<!doctype html>")
			fmt.Fprint(w, instapage.RegisterForm())
			fmt.Fprint(w, "")
			return
		}
	})
	m.Post("/register", binding.Bind(RegisterAdmin{}), func(ra RegisterAdmin) string {
		username := AdminUsername
		if !userstate.HasUser(username) {
			userstate.AddUser(username, ra.Password1, ra.Email)
			userstate.SetAdminStatus(username)
		}
		return "registered " + username
	})

	// Login admin
	m.Get("/login", func(w http.ResponseWriter, req *http.Request) {
		// TODO: Handle things differently if a regular user is logged in
		if !userstate.AdminRights(req) {
			w.Header().Add("Content-Type", "text/html")
			fmt.Fprint(w, "<!doctype html>")
			fmt.Fprint(w, instapage.LoginForm())
			fmt.Fprint(w, "")
			return
		}
	})
	m.Post("/login", binding.Bind(LoginAdmin{}), func(la LoginAdmin) string {
		username := AdminUsername
		if !userstate.HasUser(username) {
			return "FAIL must have " + username
		}
		if !userstate.CorrectPassword(username, la.Password) {
			return "FAIL password"
		}
		userstate.SetLoggedIn(username)
		return "logged in " + username
	})

	// Logout admin
	m.Any("/logout", func() string {
		username := AdminUsername
		userstate.Logout(username)
		// TODO errorcheck
		return "logged out " + username
	})

	// --- REST methods ---

	// The API uses HTTP Basic Auth instead of cookies
	//perm.AddPublicPath(API)

	// For testing the API
	m.Any(API, func(r render.Render) {
		r.JSON(http.StatusOK, map[string]interface{}{"hello": "fjaselus"})
	})

	// For adding users

	m.Post(API+"create/:username", func(params martini.Params, r render.Render) {
		username := params["username"]
		if userstate.HasUser(username) {
			r.JSON(http.StatusConflict, map[string]interface{}{"error": "user " + username + " already exists"})
			return
		}
		userstate.AddUser(username, "", "")
		if userstate.HasUser(username) {
			r.JSON(http.StatusOK, map[string]interface{}{"create": true})
		} else {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "user " + username + " was not created"})
		}
	})

	m.Post(API+"register/:username/:password/:email", func(params martini.Params, r render.Render) {
		username := params["username"]
		password := params["password"]
		password := params["email"]
		if userstate.HasUser(username) {
			r.JSON(http.StatusConflict, map[string]interface{}{"error": "user " + username + " already exists"})
			return
		}
		userstate.AddUser(username, password, email)
		if userstate.HasUser(username) {
			r.JSON(http.StatusOK, map[string]interface{}{"create": true})
		} else {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "user " + username + " was not created"})
		}
	})

	// For logging in
	m.Post(API+"login/:username/:password", func(w http.ResponseWriter, params martini.Params, r render.Render) {
		username := params["username"]
		password := params["password"]
		if userstate.CorrectPassword(username, password) {
			userstate.SetLoggedIn(username)

		}
		if !userstate.IsLoggedIn(username) {
			r.JSON(http.StatusUnauthorized, map[string]interface{}{"error": "could not log in " + username})
			return
		}
		r.JSON(http.StatusOK, map[string]interface{}{"login": true})
	})

	// For logging out
	m.Any(API+"logout/:username", func(params martini.Params, r render.Render) {
		username := params["username"]
		userstate.Logout(username)
		if userstate.IsLoggedIn(username) {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "user " + username + " is still logged in!"})
			return
		}
		r.JSON(http.StatusOK, map[string]interface{}{"logout": true})
	})

	// For login status
	m.Any(API+"status/:username", func(params martini.Params, r render.Render) {
		username := params["username"]
		if userstate.IsLoggedIn(username) {
			r.JSON(http.StatusOK, map[string]interface{}{"login": true})
		} else {
			r.JSON(http.StatusOK, map[string]interface{}{"login": "false"})
		}
	})

	// Score POST og GET + timestamp
	m.Post(API+"score/:username/:score", func(params martini.Params, r render.Render) {
		username := params["username"]
		score := params["score"]

		if !userstate.HasUser(username) {
			r.JSON(http.StatusNotFound, map[string]interface{}{"error": "no such user " + username})
			return
		}

		users := userstate.GetUsers()
		users.Set(username, "score", score)

		r.JSON(http.StatusOK, map[string]interface{}{"score set": true})
	})
	m.Get(API+"score/:username", func(params martini.Params, r render.Render) {
		username := params["username"]

		if !userstate.HasUser(username) {
			r.JSON(http.StatusNotFound, map[string]interface{}{"error": "no such user " + username})
			return
		}

		users := userstate.GetUsers()
		score, err := users.Get(username, "score")
		if err != nil {
			r.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "could not get score for " + username})
			return
		}

		r.JSON(http.StatusOK, map[string]interface{}{"score": score})
	})

	// Activate the permission middleware
	//m.Use(fizz.All())

	// Share the files in static
	m.Use(martini.Static("static"))

	// Only enable HTTP Basic Auth for paths that starts with "/api"
	m.Use(auth.BasicFunc(func(username, password string) bool {
		// Check if the admin user has the correct password, as registered for the admin user
		return auth.SecureCompare(AdminUsername, username) && userstate.CorrectPassword(AdminUsername, password)
	}, "/api"))

	m.Run() // port 3000 by default
}
<|endoftext|>


<commit_before>// Create a simulator to test out big money strategy.
package main

import (
	"container/heap"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"runtime/pprof"
	"time"
)

var cpuprofile = flag.String("cpuprofile", "", "Path to profile file")

type Node struct {
	S     State
	B     Board
	Moves int
}
type Nodes []Node

func (n Nodes) Len() int { return len(n) }
func (n Nodes) Swap(i, j int) {
	n[i], n[j] = n[j], n[i]
}
func (n Nodes) Less(i, j int) bool {
	mi := n[i].Moves
	mj := n[j].Moves
	if mi == mj {
		vi := n[i].S.TotalVictory()
		vj := n[j].S.TotalVictory()
		return vi > vj
	}
	return mi < mj
}

func (n *Nodes) Push(x interface{}) {
	node := x.(Node)
	*n = append(*n, node)
}

func (n *Nodes) Pop() interface{} {
	old := *n
	l := len(old) - 1
	node := old[l]
	*n = old[0:l]
	return node
}

func shuffle(cards []string) {
	for i := range cards {
		j := rand.Intn(i + 1)
		cards[i], cards[j] = cards[j], cards[i]
	}
}

func addCard(b *Board, s *State, name string) bool {
	card, ok := GetCard(name)
	if !ok {
		panic("Invalid card")
		return false
	}

	if s.Value() < GetCost(card) {
		return false
	}

	card, ok = b.Get(name)
	if !ok {
		return false
	}

	s.AddCardAndDiscardHand(card)
	return true
}

func PlayTurn(n Node) []Node {
	var result []Node
	n.S.DrawHand()

	for _, name := range CardNames() {
		ds := n.S.NewCopy()
		db := n.B.NewCopy()
		if ok := addCard(&db, &ds, name); ok {
			nn := Node{S: ds, B: db, Moves: n.Moves + 1}
			result = append(result, nn)
		}
	}
	return result
}

func MainLoop() {
	var board Board
	board.Init(2)

	var state State
	state.Init()

	n := Node{S: state, B: board}
	h := new(Nodes)
	heap.Init(h)
	heap.Push(h, n)

	attempt := 0
	for {
		fmt.Printf("\nAttempt: %d\n", attempt)
		attempt += 1

		tp := heap.Pop(h)
		node := tp.(Node)

		node.S.Print()
		fmt.Printf("In moves: %d\n", node.Moves)

		if node.S.TotalVictory() >= 24 {
			fmt.Printf("Reached victory in %d moves\n", node.Moves)

			break
		}
		next := PlayTurn(node)
		for _, nn := range next {
			heap.Push(h, nn)
		}
		// q = append(q, next...)
		// sort.Sort(Nodes(q))
	}
}

func main() {
	rand.Seed(time.Now().UnixNano())
	CardInit()

	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	MainLoop()
	fmt.Println("DONE")
}
<commit_msg>Shorten logging<commit_after>// Create a simulator to test out big money strategy.
package main

import (
	"container/heap"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"runtime/pprof"
	"time"
)

var cpuprofile = flag.String("cpuprofile", "", "Path to profile file")

type Node struct {
	S     State
	B     Board
	Moves int
}
type Nodes []Node

func (n Nodes) Len() int { return len(n) }
func (n Nodes) Swap(i, j int) {
	n[i], n[j] = n[j], n[i]
}
func (n Nodes) Less(i, j int) bool {
	mi := n[i].Moves
	mj := n[j].Moves
	if mi == mj {
		vi := n[i].S.TotalVictory()
		vj := n[j].S.TotalVictory()
		return vi > vj
	}
	return mi < mj
}

func (n *Nodes) Push(x interface{}) {
	node := x.(Node)
	*n = append(*n, node)
}

func (n *Nodes) Pop() interface{} {
	old := *n
	l := len(old) - 1
	node := old[l]
	*n = old[0:l]
	return node
}

func shuffle(cards []string) {
	for i := range cards {
		j := rand.Intn(i + 1)
		cards[i], cards[j] = cards[j], cards[i]
	}
}

func addCard(b *Board, s *State, name string) bool {
	card, ok := GetCard(name)
	if !ok {
		panic("Invalid card")
		return false
	}

	if s.Value() < GetCost(card) {
		return false
	}

	card, ok = b.Get(name)
	if !ok {
		return false
	}

	s.AddCardAndDiscardHand(card)
	return true
}

func PlayTurn(n Node) []Node {
	var result []Node
	n.S.DrawHand()

	for _, name := range CardNames() {
		ds := n.S.NewCopy()
		db := n.B.NewCopy()
		if ok := addCard(&db, &ds, name); ok {
			nn := Node{S: ds, B: db, Moves: n.Moves + 1}
			result = append(result, nn)
		}
	}
	return result
}

func MainLoop() {
	var board Board
	board.Init(2)

	var state State
	state.Init()

	n := Node{S: state, B: board}
	h := new(Nodes)
	heap.Init(h)
	heap.Push(h, n)

	attempt := 0
	for {
		attempt += 1

		tp := heap.Pop(h)
		node := tp.(Node)

		if attempt%1000 == 0 {
			fmt.Printf("Iter [%d] Moves: %d Victory Points: %d\n",
				attempt, node.Moves, node.S.TotalVictory())
		}

		if node.S.TotalVictory() >= 24 {
			fmt.Printf("Reached victory in %d moves\n", node.Moves)
			node.S.Print()

			break
		}
		next := PlayTurn(node)
		for _, nn := range next {
			heap.Push(h, nn)
		}
		// q = append(q, next...)
		// sort.Sort(Nodes(q))
	}
}

func main() {
	rand.Seed(time.Now().UnixNano())
	CardInit()

	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	MainLoop()
	fmt.Println("DONE")
}
<|endoftext|>


<commit_before>package main

import (
    "io/ioutil"
    "os"
    "os/exec"
    "github.com/fatih/color"
)

var (
    progPath string
    testDir string
)

func main() {
    initVars()

    cmd := exec.Command(progPath)
    err := cmd.Run()
    if err != nil {
        color.Red("Error running program:\n" + err.Error())
        os.Exit(0)
    }
}

func initVars() {
    numArgs := len(os.Args)
    if numArgs >= 2 {
        progPath = os.Args[1]
    } else {
        color.Red("Please specify exectable as first argument")
        os.Exit(0)
    }

    if numArgs >= 3 {
        testDir = os.Args[2]
    } else {
        x, err := os.Getwd()
        if err != nil {
            color.Red("Error getting current working directory:\n" + err.Error())
            os.Exit(0)
        }
        testDir = x
    }
}

func copyTestData(fileName string) {
    b, err := ioutil.ReadFile(fileName + ".in")
    if err != nil {
        panic(err)
    }

    err = ioutil.WriteFile(progPath + ".in", b, 0644)
    if err != nil {
        panic(err)
    }
}
<commit_msg>add function to compare outputs<commit_after>package main

import (
    "io/ioutil"
    "os"
    "os/exec"
    "github.com/fatih/color"
)

var (
    progPath string
    testDir string
)

func main() {
    initVars()

    cmd := exec.Command(progPath)
    err := cmd.Run()
    if err != nil {
        color.Red("Error running program:\n" + err.Error())
        os.Exit(0)
    }
}

func initVars() {
    numArgs := len(os.Args)
    if numArgs >= 2 {
        progPath = os.Args[1]
    } else {
        color.Red("Please specify exectable as first argument")
        os.Exit(0)
    }

    if numArgs >= 3 {
        testDir = os.Args[2]
    } else {
        x, err := os.Getwd()
        if err != nil {
            color.Red("Error getting current working directory:\n" + err.Error())
            os.Exit(0)
        }
        testDir = x
    }
}

func copyTestData(fileName string) {
    b, err := ioutil.ReadFile(fileName + ".in")
    if err != nil {
        panic(err)
    }

    err = ioutil.WriteFile(progPath + ".in", b, 0644)
    if err != nil {
        panic(err)
    }
}

// if outputs are not same, return position of nonequivalence; otherwise return -1
func compareOutput(a, b []byte) int {
    fileLen := len(a)
    for i := 0; i < fileLen; i++ {
        if a[i] != b[i] {
            return i
        }
    }
    return -1
}
<|endoftext|>