<commit_before>// Copyright (c) 2014 The SkyDNS Authors. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/coreos/go-etcd/etcd"
	"github.com/miekg/dns"

	backendetcd "github.com/skynetservices/skydns/backends/etcd"
	"github.com/skynetservices/skydns/msg"
	"github.com/skynetservices/skydns/server"
	"github.com/skynetservices/skydns/stats"
)

var (
	tlskey     = ""
	tlspem     = ""
	cacert     = ""
	config     = &server.Config{ReadTimeout: 0, Domain: "", DnsAddr: "", DNSSEC: ""}
	nameserver = ""
	machine    = ""
	discover   = false
	stub       = false
)

func env(key, def string) string {
	if x := os.Getenv(key); x != "" {
		return x
	}
	return def
}

func init() {
	flag.StringVar(&config.Domain, "domain", env("SKYDNS_DOMAIN", "skydns.local."), "domain to anchor requests to (SKYDNS_DOMAIN)")
	flag.StringVar(&config.DnsAddr, "addr", env("SKYDNS_ADDR", "127.0.0.1:53"), "ip:port to bind to (SKYDNS_ADDR)")
	flag.StringVar(&nameserver, "nameservers", env("SKYDNS_NAMESERVERS", ""), "nameserver address(es) to forward (non-local) queries to e.g. 8.8.8.8:53,8.8.4.4:53")
	flag.BoolVar(&config.ForwardLocal, "forward-local", false, "do not forward local queries e.g. *.skydns.local query will not forward to nameservers")
	flag.BoolVar(&config.NoRec, "no-rec", false, "do not provide a recursive service")
	flag.StringVar(&machine, "machines", env("ETCD_MACHINES", ""), "machine address(es) running etcd")
	flag.StringVar(&config.DNSSEC, "dnssec", "", "basename of DNSSEC key file e.q. Kskydns.local.+005+38250")
	flag.StringVar(&config.Local, "local", "", "optional unique value for this skydns instance")
	flag.StringVar(&tlskey, "tls-key", env("ETCD_TLSKEY", ""), "TLS Private Key path")
	flag.StringVar(&tlspem, "tls-pem", env("ETCD_TLSPEM", ""), "X509 Certificate")
	flag.StringVar(&cacert, "ca-cert", env("ETCD_CACERT", ""), "CA Certificate")
	flag.DurationVar(&config.ReadTimeout, "rtimeout", 2*time.Second, "read timeout")
	flag.BoolVar(&config.RoundRobin, "round-robin", true, "round robin A/AAAA replies")
	flag.BoolVar(&discover, "discover", false, "discover new machines by watching /v2/_etcd/machines")
	flag.BoolVar(&stub, "stubzones", false, "support stub zones")
	flag.BoolVar(&config.Verbose, "verbose", false, "log queries")
	flag.BoolVar(&config.Systemd, "systemd", false, "bind to socket(s) activated by systemd (ignore -addr)")

	// TTl
	// Minttl
	flag.StringVar(&config.Hostmaster, "hostmaster", "hostmaster@skydns.local.", "hostmaster email address to use")
	flag.IntVar(&config.SCache, "scache", server.SCacheCapacity, "capacity of the signature cache")
	flag.IntVar(&config.RCache, "rcache", 0, "capacity of the response cache") // default to 0 for now
	flag.IntVar(&config.RCacheTtl, "rcache-ttl", server.RCacheTtl, "TTL of the response cache")

	flag.StringVar(&msg.PathPrefix, "path-prefix", env("SKYDNS_PATH_PREFIX", "skydns"), "backend(etcd) path prefix, default: skydns")
}

func main() {
	flag.Parse()
	machines := strings.Split(machine, ",")
	client := newClient(machines, tlspem, tlskey, cacert)

	if nameserver != "" {
		for _, hostPort := range strings.Split(nameserver, ",") {
			if err := validateHostPort(hostPort); err != nil {
				log.Fatalf("skydns: nameserver is invalid: %s", err)
			}
			config.Nameservers = append(config.Nameservers, hostPort)
		}
	}
	if err := validateHostPort(config.DnsAddr); err != nil {
		log.Fatalf("skydns: addr is invalid: %s", err)
	}

	if err := loadConfig(client, config); err != nil {
		log.Fatalf("skydns: %s", err)
	}
	if err := server.SetDefaults(config); err != nil {
		log.Fatalf("skydns defaults could not be set from /etc/resolv.conf: %v", err)
	}

	if config.Local != "" {
		config.Local = dns.Fqdn(config.Local)
	}

	backend := backendetcd.NewBackend(client, &backendetcd.Config{
		Ttl:      config.Ttl,
		Priority: config.Priority,
	})
	s := server.New(backend, config)

	if discover {
		go func() {
			recv := make(chan *etcd.Response)
			go client.Watch("/_etcd/machines/", 0, true, recv, nil)
			duration := 1 * time.Second
			for {
				select {
				case n := <-recv:
					if n != nil {
						if client := updateClient(n, tlskey, tlspem, cacert); client != nil {
							backend.UpdateClient(client)
						}
						duration = 1 * time.Second // reset
					} else {
						// we can see an n == nil, probably when we can't connect to etcd.
						log.Printf("skydns: etcd machine cluster update failed, sleeping %s + ~3s", duration)
						time.Sleep(duration + (time.Duration(rand.Float32() * 3e9))) // Add some random.
						duration *= 2
						if duration > 32*time.Second {
							duration = 32 * time.Second
						}
					}
				}
			}
		}()
	}

	if stub {
		s.UpdateStubZones()
		go func() {
			recv := make(chan *etcd.Response)
			go client.Watch(msg.Path(config.Domain)+"/dns/stub/", 0, true, recv, nil)
			duration := 1 * time.Second
			for {
				select {
				case n := <-recv:
					if n != nil {
						s.UpdateStubZones()
						log.Printf("skydns: stubzone update")
						duration = 1 * time.Second // reset
					} else {
						// we can see an n == nil, probably when we can't connect to etcd.
						log.Printf("skydns: stubzone update failed, sleeping %s + ~3s", duration)
						time.Sleep(duration + (time.Duration(rand.Float32() * 3e9))) // Add some random.
						duration *= 2
						if duration > 32*time.Second {
							duration = 32 * time.Second
						}
					}
				}
			}
		}()
	}

	stats.Collect()  // Graphite
	server.Metrics() // Prometheus

	if err := s.Run(); err != nil {
		log.Fatalf("skydns: %s", err)
	}
}

func loadConfig(client *etcd.Client, config *server.Config) error {
	// Override what isn't set yet from the command line.
	n, err := client.Get("/"+msg.PathPrefix+"/config", false, false)
	if err != nil {
		log.Printf("skydns: falling back to default configuration, could not read from etcd: %s", err)
		return nil
	}
	if err := json.Unmarshal([]byte(n.Node.Value), config); err != nil {
		return fmt.Errorf("failed to unmarshal config: %s", err.Error())
	}
	return nil
}

func validateHostPort(hostPort string) error {
	host, port, err := net.SplitHostPort(hostPort)
	if err != nil {
		return err
	}
	if ip := net.ParseIP(host); ip == nil {
		return fmt.Errorf("bad IP address: %s", host)
	}

	if p, _ := strconv.Atoi(port); p < 1 || p > 65535 {
		return fmt.Errorf("bad port number %s", port)
	}
	return nil
}

func newClient(machines []string, tlsCert, tlsKey, tlsCACert string) (client *etcd.Client) {
	// set default if not specified in env
	if len(machines) == 1 && machines[0] == "" {
		machines[0] = "http://127.0.0.1:4001"
	}
	if strings.HasPrefix(machines[0], "https://") {
		var err error
		// TODO(miek): machines is local, the rest is global, ugly.
		if client, err = etcd.NewTLSClient(machines, tlsCert, tlsKey, tlsCACert); err != nil {
			// TODO(miek): would be nice if this wasn't a fatal error
			log.Fatalf("skydns: failure to connect: %s", err)
		}
		return client
	}
	return etcd.NewClient(machines)
}

// updateClient updates the client with the machines found in v2/_etcd/machines.
func updateClient(resp *etcd.Response, tlsCert, tlsKey, tlsCACert string) (client *etcd.Client) {
	machines := make([]string, 0, 3)
	for _, m := range resp.Node.Nodes {
		u, e := url.Parse(m.Value)
		if e != nil {
			continue
		}
		// etcd=bla&raft=bliep
		// TODO(miek): surely there is a better way to do this
		ms := strings.Split(u.String(), "&")
		if len(ms) == 0 {
			continue
		}
		if len(ms[0]) < 5 {
			continue
		}
		machines = append(machines, ms[0][5:])
	}
	// When CoreOS (and thus etcd) crash this call back seems to also trigger, but we
	// don't have any machines. Don't trigger this update then, as a) it
	// crashes SkyDNS and b) potentially leaves with no machines to connect to.
	// Keep the old ones and hope they still work and wait for another update
	// in the future.
	if len(machines) > 0 {
		log.Printf("skydns: setting new etcd cluster to %v", machines)
		return newClient(machines, tlsCert, tlsKey, tlsCACert)
	}
	return nil
}
<commit_msg>for go1.4<commit_after>// Copyright (c) 2014 The SkyDNS Authors. All rights reserved.
// Use of this source code is governed by The MIT License (MIT) that can be
// found in the LICENSE file.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"net"
	"net/url"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/coreos/go-etcd/etcd"
	"github.com/miekg/dns"

	backendetcd "github.com/skynetservices/skydns/backends/etcd"
	"github.com/skynetservices/skydns/msg"
	"github.com/skynetservices/skydns/server"
	"github.com/skynetservices/skydns/stats"
)

var (
	tlskey     = ""
	tlspem     = ""
	cacert     = ""
	config     = &server.Config{ReadTimeout: 0, Domain: "", DnsAddr: "", DNSSEC: ""}
	nameserver = ""
	machine    = ""
	discover   = false
	stub       = false
)

func env(key, def string) string {
	if x := os.Getenv(key); x != "" {
		return x
	}
	return def
}

func init() {
	flag.StringVar(&config.Domain, "domain", env("SKYDNS_DOMAIN", "skydns.local."), "domain to anchor requests to (SKYDNS_DOMAIN)")
	flag.StringVar(&config.DnsAddr, "addr", env("SKYDNS_ADDR", "127.0.0.1:53"), "ip:port to bind to (SKYDNS_ADDR)")
	flag.StringVar(&nameserver, "nameservers", env("SKYDNS_NAMESERVERS", ""), "nameserver address(es) to forward (non-local) queries to e.g. 8.8.8.8:53,8.8.4.4:53")
	flag.BoolVar(&config.ForwardLocal, "forward-local", false, "do not forward local queries e.g. *.skydns.local query will not forward to nameservers")
	flag.BoolVar(&config.NoRec, "no-rec", false, "do not provide a recursive service")
	flag.StringVar(&machine, "machines", env("ETCD_MACHINES", ""), "machine address(es) running etcd")
	flag.StringVar(&config.DNSSEC, "dnssec", "", "basename of DNSSEC key file e.q. Kskydns.local.+005+38250")
	flag.StringVar(&config.Local, "local", "", "optional unique value for this skydns instance")
	flag.StringVar(&tlskey, "tls-key", env("ETCD_TLSKEY", ""), "TLS Private Key path")
	flag.StringVar(&tlspem, "tls-pem", env("ETCD_TLSPEM", ""), "X509 Certificate")
	flag.StringVar(&cacert, "ca-cert", env("ETCD_CACERT", ""), "CA Certificate")
	flag.DurationVar(&config.ReadTimeout, "rtimeout", 2*time.Second, "read timeout")
	flag.BoolVar(&config.RoundRobin, "round-robin", true, "round robin A/AAAA replies")
	flag.BoolVar(&discover, "discover", false, "discover new machines by watching /v2/_etcd/machines")
	flag.BoolVar(&stub, "stubzones", false, "support stub zones")
	flag.BoolVar(&config.Verbose, "verbose", false, "log queries")
	flag.BoolVar(&config.Systemd, "systemd", false, "bind to socket(s) activated by systemd (ignore -addr)")

	// TTl
	// Minttl
	flag.StringVar(&config.Hostmaster, "hostmaster", "hostmaster@skydns.local.", "hostmaster email address to use")
	flag.IntVar(&config.SCache, "scache", server.SCacheCapacity, "capacity of the signature cache")
	flag.IntVar(&config.RCache, "rcache", 0, "capacity of the response cache") // default to 0 for now
	flag.IntVar(&config.RCacheTtl, "rcache-ttl", server.RCacheTtl, "TTL of the response cache")

	flag.StringVar(&msg.PathPrefix, "path-prefix", env("SKYDNS_PATH_PREFIX", "skydns"), "backend(etcd) path prefix, default: skydns")
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()
	machines := strings.Split(machine, ",")
	client := newClient(machines, tlspem, tlskey, cacert)

	if nameserver != "" {
		for _, hostPort := range strings.Split(nameserver, ",") {
			if err := validateHostPort(hostPort); err != nil {
				log.Fatalf("skydns: nameserver is invalid: %s", err)
			}
			config.Nameservers = append(config.Nameservers, hostPort)
		}
	}
	if err := validateHostPort(config.DnsAddr); err != nil {
		log.Fatalf("skydns: addr is invalid: %s", err)
	}

	if err := loadConfig(client, config); err != nil {
		log.Fatalf("skydns: %s", err)
	}
	if err := server.SetDefaults(config); err != nil {
		log.Fatalf("skydns defaults could not be set from /etc/resolv.conf: %v", err)
	}

	if config.Local != "" {
		config.Local = dns.Fqdn(config.Local)
	}

	backend := backendetcd.NewBackend(client, &backendetcd.Config{
		Ttl:      config.Ttl,
		Priority: config.Priority,
	})
	s := server.New(backend, config)

	if discover {
		go func() {
			recv := make(chan *etcd.Response)
			go client.Watch("/_etcd/machines/", 0, true, recv, nil)
			duration := 1 * time.Second
			for {
				select {
				case n := <-recv:
					if n != nil {
						if client := updateClient(n, tlskey, tlspem, cacert); client != nil {
							backend.UpdateClient(client)
						}
						duration = 1 * time.Second // reset
					} else {
						// we can see an n == nil, probably when we can't connect to etcd.
						log.Printf("skydns: etcd machine cluster update failed, sleeping %s + ~3s", duration)
						time.Sleep(duration + (time.Duration(rand.Float32() * 3e9))) // Add some random.
						duration *= 2
						if duration > 32*time.Second {
							duration = 32 * time.Second
						}
					}
				}
			}
		}()
	}

	if stub {
		s.UpdateStubZones()
		go func() {
			recv := make(chan *etcd.Response)
			go client.Watch(msg.Path(config.Domain)+"/dns/stub/", 0, true, recv, nil)
			duration := 1 * time.Second
			for {
				select {
				case n := <-recv:
					if n != nil {
						s.UpdateStubZones()
						log.Printf("skydns: stubzone update")
						duration = 1 * time.Second // reset
					} else {
						// we can see an n == nil, probably when we can't connect to etcd.
						log.Printf("skydns: stubzone update failed, sleeping %s + ~3s", duration)
						time.Sleep(duration + (time.Duration(rand.Float32() * 3e9))) // Add some random.
						duration *= 2
						if duration > 32*time.Second {
							duration = 32 * time.Second
						}
					}
				}
			}
		}()
	}

	stats.Collect()  // Graphite
	server.Metrics() // Prometheus

	if err := s.Run(); err != nil {
		log.Fatalf("skydns: %s", err)
	}
}

func loadConfig(client *etcd.Client, config *server.Config) error {
	// Override what isn't set yet from the command line.
	n, err := client.Get("/"+msg.PathPrefix+"/config", false, false)
	if err != nil {
		log.Printf("skydns: falling back to default configuration, could not read from etcd: %s", err)
		return nil
	}
	if err := json.Unmarshal([]byte(n.Node.Value), config); err != nil {
		return fmt.Errorf("failed to unmarshal config: %s", err.Error())
	}
	return nil
}

func validateHostPort(hostPort string) error {
	host, port, err := net.SplitHostPort(hostPort)
	if err != nil {
		return err
	}
	if ip := net.ParseIP(host); ip == nil {
		return fmt.Errorf("bad IP address: %s", host)
	}

	if p, _ := strconv.Atoi(port); p < 1 || p > 65535 {
		return fmt.Errorf("bad port number %s", port)
	}
	return nil
}

func newClient(machines []string, tlsCert, tlsKey, tlsCACert string) (client *etcd.Client) {
	// set default if not specified in env
	if len(machines) == 1 && machines[0] == "" {
		machines[0] = "http://127.0.0.1:4001"
	}
	if strings.HasPrefix(machines[0], "https://") {
		var err error
		// TODO(miek): machines is local, the rest is global, ugly.
		if client, err = etcd.NewTLSClient(machines, tlsCert, tlsKey, tlsCACert); err != nil {
			// TODO(miek): would be nice if this wasn't a fatal error
			log.Fatalf("skydns: failure to connect: %s", err)
		}
		return client
	}
	return etcd.NewClient(machines)
}

// updateClient updates the client with the machines found in v2/_etcd/machines.
func updateClient(resp *etcd.Response, tlsCert, tlsKey, tlsCACert string) (client *etcd.Client) {
	machines := make([]string, 0, 3)
	for _, m := range resp.Node.Nodes {
		u, e := url.Parse(m.Value)
		if e != nil {
			continue
		}
		// etcd=bla&raft=bliep
		// TODO(miek): surely there is a better way to do this
		ms := strings.Split(u.String(), "&")
		if len(ms) == 0 {
			continue
		}
		if len(ms[0]) < 5 {
			continue
		}
		machines = append(machines, ms[0][5:])
	}
	// When CoreOS (and thus etcd) crash this call back seems to also trigger, but we
	// don't have any machines. Don't trigger this update then, as a) it
	// crashes SkyDNS and b) potentially leaves with no machines to connect to.
	// Keep the old ones and hope they still work and wait for another update
	// in the future.
	if len(machines) > 0 {
		log.Printf("skydns: setting new etcd cluster to %v", machines)
		return newClient(machines, tlsCert, tlsKey, tlsCACert)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"time"

	"github.com/fujiwara/shapeio"
)

const (
	defaultMessage = "time:2013-11-20 23:39:42 +0900\tlevel:ERROR\tmethod:POST\turi:/api/v1/people\treqtime:3.1983877060667103"
)

var (
	messages []string
	bufSize  = 1024 * 1024
)

func main() {
	var (
		second  int64
		output  string
		input   string
		message string
		rate    float64
	)

	flag.Int64Var(&second, "s", 1, "Duration of running in second")
	flag.StringVar(&output, "o", "dummy.log", "Output file")
	flag.StringVar(&input, "i", "", "Input file (Output messages by reading lines of the file in rotation)")
	flag.StringVar(&message, "m", defaultMessage, "Output message")
	flag.Float64Var(&rate, "r", 0, "Number of generating messages per second")
	flag.Parse()

	if input != "" {
		err := loadMessages(input)
		if err != nil {
			die(err)
		}
	} else {
		messages = []string{message + "\n"}
	}
	f, err := os.Create(output)
	if err != nil {
		die(err)
	}
	defer f.Close()

	w := shapeio.NewWriter(f)
	if rate != 0 {
		avgMessageSize := 0
		for _, m := range messages {
			avgMessageSize += len(m)
		}
		avgMessageSize = avgMessageSize / len(messages)
		limit := float64(avgMessageSize) * rate
		w.SetRateLimit(limit)
	}
	bw := bufio.NewWriterSize(w, bufSize)

	timer := time.NewTimer(time.Duration(second) * time.Second)
	go func() {
		n := len(messages)
		for i := 0; ; i++ {
			io.WriteString(bw, messages[i%n])
		}
	}()
	<-timer.C
}

func die(err error) {
	fmt.Println(err)
	os.Exit(1)
}

func loadMessages(filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		messages = append(messages, scanner.Text()+"\n")
	}
	if err := scanner.Err(); err != nil {
		return err
	}
	return nil
}
<commit_msg>adjust bufSize by rate<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"time"

	"github.com/fujiwara/shapeio"
)

const (
	defaultMessage = "time:2013-11-20 23:39:42 +0900\tlevel:ERROR\tmethod:POST\turi:/api/v1/people\treqtime:3.1983877060667103"
)

var (
	messages       []string
	defaultBufSize = 1024 * 1024
)

func main() {
	var (
		second  int64
		output  string
		input   string
		message string
		rate    float64
	)

	flag.Int64Var(&second, "s", 1, "Duration of running in second")
	flag.StringVar(&output, "o", "dummy.log", "Output file")
	flag.StringVar(&input, "i", "", "Input file (Output messages by reading lines of the file in rotation)")
	flag.StringVar(&message, "m", defaultMessage, "Output message")
	flag.Float64Var(&rate, "r", 0, "Number of generating messages per second")
	flag.Parse()

	if input != "" {
		err := loadMessages(input)
		if err != nil {
			die(err)
		}
	} else {
		messages = []string{message + "\n"}
	}
	f, err := os.Create(output)
	if err != nil {
		die(err)
	}
	defer f.Close()

	var bufSize int
	w := shapeio.NewWriter(f)
	if rate != 0 {
		avgMessageSize := 0
		for _, m := range messages {
			avgMessageSize += len(m)
		}
		avgMessageSize = avgMessageSize / len(messages)
		limit := float64(avgMessageSize) * rate
		w.SetRateLimit(limit)
		bufSize = int(limit)
	} else {
		bufSize = defaultBufSize
	}
	bw := bufio.NewWriterSize(w, bufSize)

	running := true
	done := make(chan interface{})
	timer := time.NewTimer(time.Duration(second) * time.Second)
	go func() {
		n := len(messages)
		for i := 0; running; i++ {
			io.WriteString(bw, messages[i%n])
		}
		done <- true
	}()
	<-timer.C
	running = false
	<-done
}

func die(err error) {
	fmt.Println(err)
	os.Exit(1)
}

func loadMessages(filename string) error {
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		messages = append(messages, scanner.Text()+"\n")
	}
	if err := scanner.Err(); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


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

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/martinplaner/felix/internal/felix"
)

var (
	// Version is the version string in compliance with Semantic Versioning 2.x
	Version = "undefined"
	// BuildDate is the date and time of build (UTC)
	BuildDate = "undefined"
	// GitSummary is the output of `output of git describe --tags --dirty --always`
	GitSummary = "undefined"
)

func main() {

	item := &felix.Item{
		Title:   "Title",
		URL:     "http://example.com",
		PubDate: time.Now().Add(-1 * time.Second),
	}

	link := &felix.Link{
		Title: "Title",
		URL:   "http://example.com",
	}

	printVersion()
	fmt.Println("Hello from felix!")
	fmt.Println("Item:", item)
	fmt.Println("Link:", link)
}

func printVersion() {
	fmt.Printf("%s version:%s git:%s build:%s\n", os.Args[0], Version, GitSummary, BuildDate)
}
<commit_msg>Added graceful http server for service testing.<commit_after>// Copyright 2017 Martin Planer. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/martinplaner/felix/internal/felix"
)

var (
	// Version is the version string in compliance with Semantic Versioning 2.x
	Version = "undefined"
	// BuildDate is the date and time of build (UTC)
	BuildDate = "undefined"
	// GitSummary is the output of `output of git describe --tags --dirty --always`
	GitSummary = "undefined"
)

func main() {

	item := &felix.Item{
		Title:   "Title",
		URL:     "http://example.com",
		PubDate: time.Now().Add(-1 * time.Second),
	}

	link := &felix.Link{
		Title: "Title",
		URL:   "http://example.com",
	}

	printVersion()
	fmt.Println("Hello from felix!")
	fmt.Println("Item:", item)
	fmt.Println("Link:", link)

	stopChan := make(chan os.Signal)
	signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM)

	mux := http.NewServeMux()

	mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		io.WriteString(w, "Hello from felix web!")
	}))

	srv := &http.Server{Addr: ":6554", Handler: mux}

	go func() {
		// service connections
		if err := srv.ListenAndServe(); err != nil {
			log.Printf("listen: %s\n", err)
		}
	}()

	go func() {
	L:
		for {
			select {
			case <-time.After(2 * time.Second):
				fmt.Println("Hello (again) from felix!")
			case <-stopChan:
				break L
			}
		}
	}()

	<-stopChan // wait for SIGINT
	log.Println("Shutting down server...")

	// shut down gracefully, but wait no longer than 5 seconds before halting
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	srv.Shutdown(ctx)
	cancel()

	log.Println("Server gracefully stopped")
}

func printVersion() {
	fmt.Printf("%s version:%s git:%s build:%s\n", os.Args[0], Version, GitSummary, BuildDate)
}
<|endoftext|>


<commit_before>// (c) 2016 Ilya Kaliman. ISC license.
package main

import (
	"bufio"
	"flag"
	"fmt"
	"image"
	"image/color"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"log"
	"math"
	"os"
)

type Mat struct {
	xx, xy, xz float32
	yx, yy, yz float32
	zx, zy, zz float32
}

func MatVec(m Mat, v Vec) Vec {
	return Vec{
		m.xx*v.x + m.xy*v.y + m.xz*v.z,
		m.yx*v.x + m.yy*v.y + m.yz*v.z,
		m.zx*v.x + m.zy*v.y + m.zz*v.z,
	}
}

type Vec struct {
	x, y, z float32
}

func (v *Vec) LenSq() float32 {
	return v.x*v.x + v.y*v.y + v.z*v.z
}

func (v *Vec) Len() float32 {
	return float32(math.Sqrt(float64(v.LenSq())))
}

func VecAdd(a, b Vec) Vec {
	a.Add(b)
	return a
}

func VecSub(a, b Vec) Vec {
	a.Sub(b)
	return a
}

func VecDot(a, b Vec) float32 {
	return a.x*b.x + a.y*b.y + a.z*b.z
}

func (v *Vec) Add(a Vec) {
	v.x += a.x
	v.y += a.y
	v.z += a.z
}

func (v *Vec) Sub(a Vec) {
	v.x -= a.x
	v.y -= a.y
	v.z -= a.z
}

func (v *Vec) Mul(s float32) {
	v.x *= s
	v.y *= s
	v.z *= s
}

func (v *Vec) Div(s float32) {
	v.x /= s
	v.y /= s
	v.z /= s
}

func (v *Vec) Normalize() {
	v.Div(v.Len())
}

type Ray struct {
	dir, origin Vec // dir is normalized
}

type Shape interface {
	Intersect(Ray) (bool, Vec, Vec)
}

type Sphere struct {
	pos      Vec
	radius   float32
	material Material
}

func (s *Sphere) Intersect(ray Ray) (bool, Vec, Vec) {
	return false, Vec{}, Vec{}
}

type Cylinder struct {
	center         Vec
	dir            Vec
	height, radius float32
	material       Material
}

func NewCylinder(a, b Vec) Cylinder {
	return Cylinder{}
}

func (c *Cylinder) Intersect(ray Ray) (bool, Vec, Vec) {
	return false, Vec{}, Vec{}
}

type View struct {
	width, height        int
	pos, look, right, up Vec
	viewdist             float32
}

func NewView(width, height int, radius float32) *View {
	pos := Vec{0, 0, -radius}
	v := View{
		width:  width,
		height: height,
		pos:    pos,
		look:   Vec{0, 0, 1},
		right:  Vec{1, 0, 0},
		up:     Vec{0, 1, 0},
	}
	return &v
}

func (v *View) Rotate(dx, dy, dz float32) {
}

func (v *View) Advance() {
}

func (v *View) NewRay(x, y int) Ray {
	return Ray{}
}

type Material struct {
	color color.Color
}

type Atom struct {
	name  string
	shape Sphere
}

type Bond struct {
	a, b  *Atom
	shape Cylinder
}

type Element struct {
	material Material
	radius   float32
}

var elements map[string]Element = map[string]Element{
	"H":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"He": {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"O":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"N":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"P":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
}

type Molecule struct {
	atoms []*Atom
	bonds []*Bond
}

func (m *Molecule) Center() {
	var c Vec
	for _, a := range m.atoms {
		c.Add(a.shape.pos)
	}
	c.Div(float32(len(m.atoms)))
	for _, a := range m.atoms {
		a.shape.pos.Sub(c)
	}
}

func (m *Molecule) MakeBonds() {
	const bndist = 1.6
	const bndist2 = bndist * bndist
	for _, a := range m.atoms {
		for _, b := range m.atoms {
			pa := a.shape.pos
			pb := b.shape.pos
			if d := VecSub(pa, pb); d.LenSq() < bndist2 {
				bnd := Bond{a, b, NewCylinder(pa, pb)}
				m.bonds = append(m.bonds, &bnd)
			}
		}
	}
}

func (m *Molecule) Geometry() []Shape {
	var g []Shape
	for _, a := range m.atoms {
		g = append(g, &a.shape)
	}
	for _, b := range m.bonds {
		g = append(g, &b.shape)
	}
	return g
}

func NewMolecule(path string) (*Molecule, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	m := new(Molecule)
	sc := bufio.NewScanner(f)
	sc.Scan() // skip atom count
	sc.Scan() // skip comment
	for sc.Scan() {
		var v Vec
		var s string
		fmt.Sscanf(sc.Text(), "%s %f %f %f", &s, &v.x, &v.y, &v.z)
		e, ok := elements[s]
		if !ok {
			return nil, fmt.Errorf("unknown element: %s", s)
		}
		atom := Atom{s, Sphere{v, e.radius, e.material}}
		m.atoms = append(m.atoms, &atom)
	}
	if err = sc.Err(); err != nil {
		return nil, err
	}
	if len(m.atoms) == 0 {
		return nil, fmt.Errorf("%s: no atoms found", path)
	}
	m.Center()
	m.MakeBonds()
	return m, nil
}

type Renderer struct {
	shapes []Shape
	view   View
}

func NewRenderer(g []Shape) *Renderer {
	return &Renderer{}
}

func (r *Renderer) Render() image.Image {
	rect := image.Rect(0, 0, r.view.width, r.view.height)
	img := image.NewRGBA(rect)
	return img
}

func MakePaletted(img image.Image) *image.Paletted {
	b := img.Bounds()
	pm := image.NewPaletted(b, palette.Plan9)
	draw.FloydSteinberg.Draw(pm, b, img, image.ZP)
	return pm
}

func RenderAnimation(r *Renderer, loopTime int) *gif.GIF {
	const FPS = 50
	nframes := loopTime * FPS
	var g gif.GIF
	for i := 0; i < nframes; i++ {
		img := r.Render()
		g.Image = append(g.Image, MakePaletted(img))
		g.Delay = append(g.Delay, 100/FPS)
		r.view.Advance()
	}
	return &g
}

type Color color.RGBA

func (c *Color) Set(val string) error {
	_, err := fmt.Sscanf(val, "{%d,%d,%d}", &c.R, &c.G, &c.B)
	return err
}

func (c Color) String() string {
	return fmt.Sprintf("{%d,%d,%d}", c.R, c.G, c.B)
}

var iFlag *string = flag.String("i", "input.xyz", "input file")
var oFlag *string = flag.String("o", "output.gif", "output file")
var wFlag *int = flag.Int("w", 300, "output image width")
var hFlag *int = flag.Int("h", 200, "output image height")
var xFlag *int = flag.Int("x", 0, "rotation speed along x axis")
var yFlag *int = flag.Int("y", 100, "rotation speed along y axis")
var zFlag *int = flag.Int("z", 0, "rotation speed along z axis")
var tFlag *int = flag.Int("t", 10, "animation loop time in seconds")
var bFlag Color

func main() {
	flag.Var(&bFlag, "b", "background color")
	flag.Parse()
	if *wFlag < 1 || *hFlag < 1 {
		log.Fatal("image width and height must be positive")
	}
	if *tFlag < 1 {
		log.Fatal("loop time must be positive")
	}
	m, err := NewMolecule(*iFlag)
	if err != nil {
		log.Fatal(err)
	}
	f, err := os.Create(*oFlag)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	r := NewRenderer(m.Geometry())
	g := RenderAnimation(r, *tFlag)
	if err = gif.EncodeAll(f, g); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Improve cmd line flags.<commit_after>// (c) 2016 Ilya Kaliman. ISC license.
package main

import (
	"bufio"
	"flag"
	"fmt"
	"image"
	"image/color"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"log"
	"math"
	"os"
)

type Mat struct {
	xx, xy, xz float32
	yx, yy, yz float32
	zx, zy, zz float32
}

func MatVec(m Mat, v Vec) Vec {
	return Vec{
		m.xx*v.x + m.xy*v.y + m.xz*v.z,
		m.yx*v.x + m.yy*v.y + m.yz*v.z,
		m.zx*v.x + m.zy*v.y + m.zz*v.z,
	}
}

type Vec struct {
	x, y, z float32
}

func (v *Vec) LenSq() float32 {
	return v.x*v.x + v.y*v.y + v.z*v.z
}

func (v *Vec) Len() float32 {
	return float32(math.Sqrt(float64(v.LenSq())))
}

func VecAdd(a, b Vec) Vec {
	a.Add(b)
	return a
}

func VecSub(a, b Vec) Vec {
	a.Sub(b)
	return a
}

func VecDot(a, b Vec) float32 {
	return a.x*b.x + a.y*b.y + a.z*b.z
}

func (v *Vec) Add(a Vec) {
	v.x += a.x
	v.y += a.y
	v.z += a.z
}

func (v *Vec) Sub(a Vec) {
	v.x -= a.x
	v.y -= a.y
	v.z -= a.z
}

func (v *Vec) Mul(s float32) {
	v.x *= s
	v.y *= s
	v.z *= s
}

func (v *Vec) Div(s float32) {
	v.x /= s
	v.y /= s
	v.z /= s
}

func (v *Vec) Normalize() {
	v.Div(v.Len())
}

type Ray struct {
	dir, origin Vec // dir is normalized
}

type Shape interface {
	Intersect(Ray) (bool, Vec, Vec)
}

type Sphere struct {
	pos      Vec
	radius   float32
	material Material
}

func (s *Sphere) Intersect(ray Ray) (bool, Vec, Vec) {
	return false, Vec{}, Vec{}
}

type Cylinder struct {
	center         Vec
	dir            Vec
	height, radius float32
	material       Material
}

func NewCylinder(a, b Vec) Cylinder {
	return Cylinder{}
}

func (c *Cylinder) Intersect(ray Ray) (bool, Vec, Vec) {
	return false, Vec{}, Vec{}
}

type View struct {
	width, height        int
	pos, look, right, up Vec
	viewdist             float32
}

func NewView(width, height int, radius float32) *View {
	pos := Vec{0, 0, -radius}
	v := View{
		width:  width,
		height: height,
		pos:    pos,
		look:   Vec{0, 0, 1},
		right:  Vec{1, 0, 0},
		up:     Vec{0, 1, 0},
	}
	return &v
}

func (v *View) Rotate(dx, dy, dz float32) {
}

func (v *View) Advance(angxyz [3]float32) {
}

func (v *View) NewRay(x, y int) Ray {
	return Ray{}
}

type Material struct {
	color color.Color
}

type Atom struct {
	name  string
	shape Sphere
}

type Bond struct {
	a, b  *Atom
	shape Cylinder
}

type Element struct {
	material Material
	radius   float32
}

var elements map[string]Element = map[string]Element{
	"H":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"He": {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"O":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"N":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
	"P":  {Material{color: color.RGBA{255, 255, 255, 255}}, 1.0},
}

type Molecule struct {
	atoms []*Atom
	bonds []*Bond
}

func (m *Molecule) Center() {
	var c Vec
	for _, a := range m.atoms {
		c.Add(a.shape.pos)
	}
	c.Div(float32(len(m.atoms)))
	for _, a := range m.atoms {
		a.shape.pos.Sub(c)
	}
}

func (m *Molecule) MakeBonds() {
	const bndist = 1.6
	const bndist2 = bndist * bndist
	for _, a := range m.atoms {
		for _, b := range m.atoms {
			pa := a.shape.pos
			pb := b.shape.pos
			if d := VecSub(pa, pb); d.LenSq() < bndist2 {
				bnd := Bond{a, b, NewCylinder(pa, pb)}
				m.bonds = append(m.bonds, &bnd)
			}
		}
	}
}

func (m *Molecule) Geometry() []Shape {
	var g []Shape
	for _, a := range m.atoms {
		g = append(g, &a.shape)
	}
	for _, b := range m.bonds {
		g = append(g, &b.shape)
	}
	return g
}

func NewMolecule(path string) (*Molecule, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	m := new(Molecule)
	sc := bufio.NewScanner(f)
	sc.Scan() // skip atom count
	sc.Scan() // skip comment
	for sc.Scan() {
		var v Vec
		var s string
		fmt.Sscanf(sc.Text(), "%s %f %f %f", &s, &v.x, &v.y, &v.z)
		e, ok := elements[s]
		if !ok {
			return nil, fmt.Errorf("unknown element: %s", s)
		}
		atom := Atom{s, Sphere{v, e.radius, e.material}}
		m.atoms = append(m.atoms, &atom)
	}
	if err = sc.Err(); err != nil {
		return nil, err
	}
	if len(m.atoms) == 0 {
		return nil, fmt.Errorf("%s: no atoms found", path)
	}
	m.Center()
	m.MakeBonds()
	return m, nil
}

type Renderer struct {
	shapes []Shape
	view   *View
	bg     color.RGBA
}

func NewRenderer(shapes []Shape, bg color.RGBA, w, h int) *Renderer {
	var r float32
	return &Renderer{
		shapes: shapes,
		view:   NewView(w, h, r),
		bg:     bg,
	}
}

func (r *Renderer) Advance(angxyz [3]float32) {
	r.view.Advance(angxyz)
}

func (r *Renderer) Render() image.Image {
	rect := image.Rect(0, 0, r.view.width, r.view.height)
	img := image.NewRGBA(rect)
	return img
}

func MakePaletted(img image.Image) *image.Paletted {
	b := img.Bounds()
	pm := image.NewPaletted(b, palette.Plan9)
	draw.FloydSteinberg.Draw(pm, b, img, image.ZP)
	return pm
}

func RenderAnimation(r *Renderer, loopTime int, rx, ry, rz bool) *gif.GIF {
	const FPS = 50
	nframes := loopTime * FPS
	ang := 2.0 * math.Pi / float32(nframes)
	angxyz := [3]float32{}
	if rx {
		angxyz[0] = ang
	}
	if ry {
		angxyz[1] = ang
	}
	if rz {
		angxyz[2] = ang
	}
	var g gif.GIF
	for i := 0; i < nframes; i++ {
		img := r.Render()
		g.Image = append(g.Image, MakePaletted(img))
		g.Delay = append(g.Delay, 100/FPS)
		r.Advance(angxyz)
	}
	return &g
}

var iFlag *string = flag.String("i", "input.xyz", "input file name")
var oFlag *string = flag.String("o", "output.gif", "output file name")
var wFlag *int = flag.Int("w", 300, "output image width")
var hFlag *int = flag.Int("h", 200, "output image height")
var xFlag *bool = flag.Bool("x", false, "rotate along x axis")
var yFlag *bool = flag.Bool("y", true, "rotate along y axis")
var zFlag *bool = flag.Bool("z", false, "rotate along z axis")
var tFlag *int = flag.Int("t", 10, "animation loop time in seconds")
var rFlag *uint = flag.Uint("r", 0, "background color red component")
var gFlag *uint = flag.Uint("g", 0, "background color green component")
var bFlag *uint = flag.Uint("b", 0, "background color blue component")

func main() {
	flag.Parse()
	if *wFlag < 1 || *hFlag < 1 {
		log.Fatal("image width and height must be positive")
	}
	if *tFlag < 1 {
		log.Fatal("loop time must be positive")
	}
	if *rFlag > 255 || *gFlag > 255 || *bFlag > 255 {
		log.Fatal("color component must be in the [0, 255] range")
	}
	m, err := NewMolecule(*iFlag)
	if err != nil {
		log.Fatal(err)
	}
	f, err := os.Create(*oFlag)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	bg := color.RGBA{uint8(*rFlag), uint8(*gFlag), uint8(*bFlag), 255}
	r := NewRenderer(m.Geometry(), bg, *wFlag, *hFlag)
	g := RenderAnimation(r, *tFlag, *xFlag, *yFlag, *zFlag)
	if err = gif.EncodeAll(f, g); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"encoding/base64"
	"flag"
	"log"
	"os"
	"path"
	"path/filepath"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
	"github.com/zillolo/stash/stash"
)

const (
	ArchiveExtension = ".tar.gz"
	DataStoragePath  = "/.local/share/hidden"
	DatabaseFile     = "index.db"
)

var restoreFlag = flag.Bool("restore", false, "Show a hidden file.")

func main() {
	flag.Parse()
	InitEnvironment()

	db, err := InitDB()
	if err != nil {
		log.Fatalf("%v\n", err)
	}

	log.Printf("File: %v\n", flag.Arg(0))
	if *restoreFlag {
		if err := Restore(flag.Arg(0)); err != nil {
			log.Fatalf("%v\n", err)
		}
	} else {
		if err := Hide(db, flag.Arg(0)); err != nil {
			log.Fatalf("%v\n", err)
		}
	}
}
func InitEnvironment() {
	path := path.Join(getHome(), DataStoragePath)
	if _, err := os.Stat(path); os.IsNotExist(err) {
		if err = os.Mkdir(path, 0755|os.ModeDir); err != nil {
			panic(err)
		}
	}
}

func InitDB() (db *gorm.DB, err error) {
	db, err = gorm.Open("sqlite3", path.Join(getHome(), DataStoragePath, DatabaseFile))
	if err != nil {
		return nil, err
	}

	if !db.HasTable(&stash.Entry{}) {
		db.CreateTable(&stash.Entry{})
	}
	return db, nil
}

func Hide(db *gorm.DB, root string) (err error) {
	// Compute the filename for the archive.
	name := path.Join(getDataPath(), computeFilename(root))
	name += ArchiveExtension

	// Create the file for the archive.
	file, err := os.Create(name)
	if err != nil {
		return err
	}

	if err := stash.Pack(root, file); err != nil {
		return err
	}

	// Add entry to the database.
	absPath, err := filepath.Abs(root)
	if err != nil {
		return err
	}

	entry := stash.Entry{Path: absPath}
	db.Create(&entry)
	return nil
}

func Restore(path string) (err error) {
	name := filepath.Join(getDataPath(), computeFilename(path))
	name += ArchiveExtension

	file, err := os.Open(name)
	if err != nil {
		return err
	}
	defer file.Close()

	path, err = filepath.Abs(path)
	if err != nil {
		return err
	}

	if err := stash.Unpack(filepath.Dir(path), file); err != nil {
		return err
	}
	return nil
}

func getHome() string {
	homePath := os.Getenv("HOME")
	if homePath == "" {
		panic("Hide may not be used by non-humans.")
	}
	return homePath
}

func getDataPath() string {
	return path.Join(getHome(), DataStoragePath)
}

func computeFilename(path string) string {
	hasher := sha1.New()
	hasher.Write([]byte(path))
	return base64.URLEncoding.EncodeToString(hasher.Sum(nil))
}
<commit_msg>Add command parsing<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"path"
	"strings"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
	"github.com/zillolo/stash/stash"
)

const (
	ArchiveExtension = ".tar.gz"
	DataStoragePath  = "/.local/share/hidden"
	DatabaseFile     = "index.db"
)

func main() {
	flag.Parse()
	InitEnvironment()

	_, err := InitDB()
	if err != nil {
		log.Panicf("%v\n", err)
	}

	if len(flag.Args()) < 2 {
		flag.Usage()
	}

	source := flag.Arg(0)
	switch strings.ToLower(flag.Arg(0)) {
	case "release":
		source = "/home/alex/.local/share/hidden"
		target := flag.Arg(1)
		destination := "."

		if len(flag.Args()) >= 3 {
			destination = flag.Arg(2)
		}
		if err := stash.Release(source, target, destination); err != nil {
			log.Panicf("%v\n", err)
		}
	case "stash":
		source = flag.Arg(1)
		fallthrough
	default:
		if err := stash.Stash(source, "/home/alex/.local/share/hidden"); err != nil {
			log.Panicf("%v\n", err)
		}
	}
}

func InitEnvironment() {
	path := path.Join(getHome(), DataStoragePath)
	if _, err := os.Stat(path); os.IsNotExist(err) {
		if err = os.Mkdir(path, 0755|os.ModeDir); err != nil {
			panic(err)
		}
	}
}

func InitDB() (db *gorm.DB, err error) {
	db, err = gorm.Open("sqlite3", path.Join(getHome(), DataStoragePath, DatabaseFile))
	if err != nil {
		return nil, err
	}

	if !db.HasTable(&stash.Entry{}) {
		db.CreateTable(&stash.Entry{})
	}
	return db, nil
}

//func Restore(path string) (err error) {
//	name := filepath.Join(getDataPath(), computeFilename(path))
//	name += ArchiveExtension
//
//	file, err := os.Open(name)
//	if err != nil {
//		return err
//	}
//	defer file.Close()
//
//	path, err = filepath.Abs(path)
//	if err != nil {
//		return err
//	}
//
//	if err := stash.Unpack(filepath.Dir(path), file); err != nil {
//		return err
//	}
//	return nil
//}

func getHome() string {
	homePath := os.Getenv("HOME")
	if homePath == "" {
		panic("Hide may not be used by non-humans.")
	}
	return homePath
}

func getDataPath() string {
	return path.Join(getHome(), DataStoragePath)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/Sirupsen/logrus"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"io/ioutil"
	"net/http"
	"sync"
)

type Registrar struct {
	lock    sync.RWMutex
	streams map[string]*Hub
}

func NewRegistrar() *Registrar {
	return &Registrar{
		lock:    sync.RWMutex{},
		streams: make(map[string]*Hub),
	}
}

func (r *Registrar) GetExistingHub(streamId string) *Hub {
	r.lock.RLock()
	defer r.lock.RUnlock()

	return r.streams[streamId]
}

func (r *Registrar) GetOrCreateHub(streamId string) *Hub {
	r.lock.Lock()
	defer r.lock.Unlock()

	hub, _ := r.streams[streamId]
	if hub == nil {
		hub = NewHub()
		r.streams[streamId] = hub

		go hub.MainLoop()
	}

	return hub
}

func (r *Registrar) Close(streamId string) bool {
	r.lock.Lock()
	defer r.lock.Unlock()

	if hub := r.streams[streamId]; hub != nil {
		delete(r.streams, streamId)
		hub.RequestShutdown()
		return true

	} else {
		return false
	}
}

func main() {
	router := mux.NewRouter()

	registrar := NewRegistrar()

	router.Path("/streams/{stream}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		streamId := vars["stream"]

		hub := registrar.GetExistingHub(streamId)
		if hub == nil {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		handleClientWebSocket(hub, w, req)
	})

	router.Path("/streams/{stream}/publish").Methods("GET").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		streamId := vars["stream"]

		// TODO check for access rights and stuff

		hub := registrar.GetOrCreateHub(streamId)
		if hub == nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		handleSenderWebSocket(hub, w, req)
	})

	router.Path("/streams/{stream}").Methods("DELETE").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		streamId := vars["stream"]

		if !registrar.Close(streamId) {
			w.WriteHeader(http.StatusNotFound)
		}
	})

	panic(http.ListenAndServe(":8081",
		handlers.LoggingHandler(logrus.StandardLogger().Writer(),
			handlers.RecoveryHandler()(router))))
}

func handleClientWebSocket(hub *Hub, writer http.ResponseWriter, request *http.Request) {
	socket, err := websocket.Upgrade(writer, request, nil, 0, 0)
	if err != nil {
		logrus.WithError(err).Warn("Could not upgrade websocket")
		return
	}

	hub.HandleConnection(socket)
}

func handleSenderWebSocket(hub *Hub, writer http.ResponseWriter, request *http.Request) {
	socket, err := websocket.Upgrade(writer, request, nil, 0, 0)
	if err != nil {
		logrus.WithError(err).Warn("Could not upgrade websocket")
		return
	}

	for {
		if msgType, msgContent, err := socket.NextReader(); err != nil {
			logrus.WithError(err).Warn("Error reading sender websocket, closing now.")
			socket.Close()
			break

		} else if msgType != websocket.CloseMessage {
			payload, err := ioutil.ReadAll(msgContent)
			if err != nil {
				logrus.WithError(err).Warn("Could not read a complete data frame from sender.")
				continue
			}

			logrus.WithField("type", msgType).
				WithField("bytes", len(payload)).
				Info("Received a dataframe from the server")

			// forward message to all registered clients!
			hub.Broadcast(msgType, payload)
		}
	}
}
<commit_msg>Add endpoint to list all streams, also hold stream metadata.<commit_after>package main

import (
	"encoding/json"
	"github.com/Sirupsen/logrus"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/gorilla/websocket"
	"io/ioutil"
	"net/http"
	"sync"
	"time"
)

type Stream struct {
	Id      string    `json:"id"`
	Created time.Time `json:"created"`

	hub *Hub
}

type Registrar struct {
	lock    sync.RWMutex
	streams map[string]*Stream
}

func NewRegistrar() *Registrar {
	return &Registrar{
		lock:    sync.RWMutex{},
		streams: make(map[string]*Stream),
	}
}

func (r *Registrar) GetExistingHub(streamId string) *Hub {
	r.lock.RLock()
	defer r.lock.RUnlock()

	stream := r.streams[streamId]
	if stream == nil {
		return nil
	}

	return stream.hub
}

func (r *Registrar) GetOrCreateHub(streamId string) *Hub {
	r.lock.Lock()
	defer r.lock.Unlock()

	stream, _ := r.streams[streamId]
	if stream == nil {
		stream = &Stream{
			Id:      streamId,
			Created: time.Now(),
			hub:     NewHub(),
		}

		r.streams[streamId] = stream

		go stream.hub.MainLoop()
	}

	return stream.hub
}

func (r *Registrar) GetStreams() []Stream {
	r.lock.Lock()
	defer r.lock.Unlock()

	// get a copy of the streams id.
	streams := make([]Stream, 0, len(r.streams))
	for _, stream := range r.streams {
		streams = append(streams, *stream)
	}

	return streams
}

func (r *Registrar) Close(streamId string) bool {
	r.lock.Lock()
	defer r.lock.Unlock()

	if stream := r.streams[streamId]; stream != nil {
		delete(r.streams, streamId)
		stream.hub.RequestShutdown()
		return true

	} else {
		return false
	}
}

func main() {
	router := mux.NewRouter()

	registrar := NewRegistrar()

	router.Path("/streams").Methods("GET").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		streams := registrar.GetStreams()

		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(streams)
	})

	router.Path("/streams/{stream}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		streamId := vars["stream"]

		hub := registrar.GetExistingHub(streamId)
		if hub == nil {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		handleClientWebSocket(hub, w, req)
	})

	router.Path("/streams/{stream}/publish").Methods("GET").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		streamId := vars["stream"]

		// TODO check for access rights and stuff

		hub := registrar.GetOrCreateHub(streamId)
		if hub == nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		handleSenderWebSocket(hub, w, req)
	})

	router.Path("/streams/{stream}").Methods("DELETE").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		vars := mux.Vars(req)
		streamId := vars["stream"]

		if !registrar.Close(streamId) {
			w.WriteHeader(http.StatusNotFound)
		}
	})

	panic(http.ListenAndServe(":8081",
		handlers.LoggingHandler(logrus.StandardLogger().Writer(),
			handlers.RecoveryHandler()(router))))
}

func handleClientWebSocket(hub *Hub, writer http.ResponseWriter, request *http.Request) {
	socket, err := websocket.Upgrade(writer, request, nil, 0, 0)
	if err != nil {
		logrus.WithError(err).Warn("Could not upgrade websocket")
		return
	}

	hub.HandleConnection(socket)
}

func handleSenderWebSocket(hub *Hub, writer http.ResponseWriter, request *http.Request) {
	socket, err := websocket.Upgrade(writer, request, nil, 0, 0)
	if err != nil {
		logrus.WithError(err).Warn("Could not upgrade websocket")
		return
	}

	for {
		if msgType, msgContent, err := socket.NextReader(); err != nil {
			logrus.WithError(err).Warn("Error reading sender websocket, closing now.")
			socket.Close()
			break

		} else if msgType != websocket.CloseMessage {
			payload, err := ioutil.ReadAll(msgContent)
			if err != nil {
				logrus.WithError(err).Warn("Could not read a complete data frame from sender.")
				continue
			}

			logrus.WithField("type", msgType).
				WithField("bytes", len(payload)).
				Info("Received a dataframe from the server")

			// forward message to all registered clients!
			hub.Broadcast(msgType, payload)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/labstack/echo"
	mw "github.com/labstack/echo/middleware"
	"github.com/rs/cors"
)

const fileTTL = 60 * time.Second

var baseURL = os.Getenv("BASE_URL")

func main() {
	addr := flag.String("listen", "localhost:3336", "address for server to listen")
	flag.Parse()

	// Echo instance
	e := echo.New()

	// Middleware
	e.Use(mw.Logger())
	e.Use(mw.Recover())
	e.Use(cors.Default().Handler)

	// Routes
	e.Get("/", ping)
	e.Post("/", gather)
	e.Get("/download/:name", download)

	// Start server
	e.Run(*addr)
}

func ping(c *echo.Context) error {
	return c.String(http.StatusOK, "pong\n")
}

type downloadRequest struct {
	Name string   `json:"name"`
	URLs []string `json:"urls"`
}

type downloadResponse struct {
	Name string `json:"name"`
	URL  string `json:"url"`
}

func gather(c *echo.Context) error {
	var req downloadRequest
	if err := c.Bind(&req); err != nil {
		return err
	}
	t := time.Now()
	name := req.Name + "-" + t.Format("20060102150405") + ".zip"
	// Write header quickly to prevent timeout
	c.Response().WriteHeader(http.StatusCreated)
	Download(name, req.URLs)
	// setup delayed cleanup
	go cleanup(name)
	url := baseURL + "/download/" + name
	resp := &downloadResponse{name, url}
	b, err := json.Marshal(resp)
	if err != nil {
		return err
	}
	c.Response().Header().Set(echo.ContentType, echo.ApplicationJSONCharsetUTF8)
	c.Response().Write(b)
	return
}

func download(c *echo.Context) error {
	name := c.Param("name")
	return c.File(name, name, true)
}

func cleanup(name string) {
	time.AfterFunc(fileTTL, func() {
		log.Printf("Deleting file %s", name)
		os.Remove(name)
	})
}
<commit_msg>missed nil return<commit_after>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/labstack/echo"
	mw "github.com/labstack/echo/middleware"
	"github.com/rs/cors"
)

const fileTTL = 60 * time.Second

var baseURL = os.Getenv("BASE_URL")

func main() {
	addr := flag.String("listen", "localhost:3336", "address for server to listen")
	flag.Parse()

	// Echo instance
	e := echo.New()

	// Middleware
	e.Use(mw.Logger())
	e.Use(mw.Recover())
	e.Use(cors.Default().Handler)

	// Routes
	e.Get("/", ping)
	e.Post("/", gather)
	e.Get("/download/:name", download)

	// Start server
	e.Run(*addr)
}

func ping(c *echo.Context) error {
	return c.String(http.StatusOK, "pong\n")
}

type downloadRequest struct {
	Name string   `json:"name"`
	URLs []string `json:"urls"`
}

type downloadResponse struct {
	Name string `json:"name"`
	URL  string `json:"url"`
}

func gather(c *echo.Context) error {
	var req downloadRequest
	if err := c.Bind(&req); err != nil {
		return err
	}
	t := time.Now()
	name := req.Name + "-" + t.Format("20060102150405") + ".zip"
	// Write header quickly to prevent timeout
	c.Response().WriteHeader(http.StatusCreated)
	Download(name, req.URLs)
	// setup delayed cleanup
	go cleanup(name)
	url := baseURL + "/download/" + name
	resp := &downloadResponse{name, url}
	b, err := json.Marshal(resp)
	if err != nil {
		return err
	}
	c.Response().Header().Set(echo.ContentType, echo.ApplicationJSONCharsetUTF8)
	c.Response().Write(b)
	return nil
}

func download(c *echo.Context) error {
	name := c.Param("name")
	return c.File(name, name, true)
}

func cleanup(name string) {
	time.AfterFunc(fileTTL, func() {
		log.Printf("Deleting file %s", name)
		os.Remove(name)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net/http"

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

func main() {
	socksAddr := flag.String("socks", "localhost:8000", "Address and port of SOCKS5 proxy server.")
	listenAddr := flag.String("listen", ":8080", "Listening address and port for HTTP relay proxy.")
	flag.Parse()
	// Prepare proxy relay with target SOCKS proxy
	dialer, err := proxy.SOCKS5("tcp", *socksAddr, nil, proxy.Direct)
	if err != nil {
		log.Println("error creating proxy definition:", err.Error())
		return
	}
	// Start HTTP proxy server
	log.Println("HTTP proxy relay server started on", *listenAddr, "relaying to", *socksAddr)
	log.Println(http.ListenAndServe(*listenAddr, &HTTPProxyHandler{Dialer: dialer}))
}
<commit_msg>Clarify log messages.<commit_after>package main

import (
	"flag"
	"log"
	"net/http"

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

func main() {
	socksAddr := flag.String("socks", "localhost:8000", "Address and port of SOCKS5 proxy server.")
	listenAddr := flag.String("listen", ":8080", "Listening address and port for HTTP relay proxy.")
	flag.Parse()
	// Prepare proxy relay with target SOCKS proxy
	dialer, err := proxy.SOCKS5("tcp", *socksAddr, nil, proxy.Direct)
	if err != nil {
		log.Println("Failed to create proxy definition:", err.Error())
		return
	}
	// Start HTTP proxy server
	log.Println("HTTP proxy relay server started on", *listenAddr, "relaying to SOCKS proxy", *socksAddr)
	log.Println(http.ListenAndServe(*listenAddr, &HTTPProxyHandler{Dialer: dialer}))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"gopkg.in/alecthomas/kingpin.v2"
	"net"
)

func GetIP(ipaddr string) (string, error) {
	var err error

	if ipaddr != "" {
		return ipaddr, err
	}

	var ifaces []net.Addr
	ifaces, err = net.InterfaceAddrs()
	for _, i := range ifaces {
		if ipnet, ok := i.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				ipaddr = ipnet.IP.String()
			}
		}
	}
	return ipaddr, err
}

var (
	file         = kingpin.Flag("file", "Config file").Short('f').Required().String()
	hostname     = kingpin.Flag("hostname", "Hostname").Short('h').String()
	ipaddr       = kingpin.Flag("ipaddr", "IP Address").String()
	ignoreErrors = kingpin.Flag("ignore-errors", "Ignore errors").Bool()
	host         = kingpin.Command("host", "Operate host")
	// host status
	hostStatus = host.Command("status", "Operate host status")
	// host status enable
	hostStatusEnable = hostStatus.Command("enable", "Enable host status")
	// host status disable
	hostStatusDisable = hostStatus.Command("disable", "Disable Host status")
	// host register
	hostRegister = host.Command("register", "Regist host")
	// host delete
	hostDelete = host.Command("delete", "Delete host")
	// host list
	hostList = host.Command("list", "Host list")
)

func main() {
	var err error
	kingpin.Version("0.1.1")
	subcommand := kingpin.Parse()

	log := logrus.New()

	var config Config
	config, err = LoadYAML(*file, *hostname)
	if err != nil {
		log.Fatal(err)
	}

	var consul Consul
	consul, err = NewConsul()
	if err != nil {
		log.Fatal(err)
	}

	var storage Storage
	storage, err = NewStorage(config.DBPath, config.DBPerm)
	if err != nil {
		log.Fatal(err)
	}
	defer storage.Close()

	zabbix := NewZabbix(config, consul, storage)

	err = zabbix.APILogin()
	if err != nil {
		log.Fatal(err)
	}

	switch subcommand {
	case "host status enable":
		host, err := zabbix.HostGetByHost()
		if err != nil {
			log.Fatal(err)
		}
		err = zabbix.HostEnable(host.HostId)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host status disable":
		host, err := zabbix.HostGetByHost()
		if err != nil {
			log.Fatal(err)
		}
		err = zabbix.HostDisable(host.HostId)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host register":
		ipaddr, err := GetIP(*ipaddr)
		if err != nil {
			log.Fatal(err)
		}

		interfaces := zabbix.HostInterface("", ipaddr, 1, 1, 1)

		groups, err := zabbix.HostGroupIds(config.HostGroups)
		if err != nil {
			log.Fatal(err)
		}

		templates, err := zabbix.Templates(config.Templates)
		if err != nil {
			log.Fatal(err)
		}

		err = zabbix.HostCreate(config.Hostname, groups, interfaces, templates)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host delete":
		host, err := zabbix.HostGetByHost()
		if err != nil {
			log.Fatal(err)
		}
		err = zabbix.HostDelete(host.HostId)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host list":
		zabbixHosts, err := zabbix.EnableHosts()
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}

		for _, zHost := range zabbixHosts {
			fmt.Println(zHost.Hostname, zHost.IPAddr)
		}
	case "host proxy":
	}
}
<commit_msg>fix ignore-errors<commit_after>package main

import (
	"fmt"
	"github.com/Sirupsen/logrus"
	"gopkg.in/alecthomas/kingpin.v2"
	"net"
)

func GetIP(ipaddr string) (string, error) {
	var err error

	if ipaddr != "" {
		return ipaddr, err
	}

	var ifaces []net.Addr
	ifaces, err = net.InterfaceAddrs()
	for _, i := range ifaces {
		if ipnet, ok := i.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				ipaddr = ipnet.IP.String()
			}
		}
	}
	return ipaddr, err
}

var (
	file         = kingpin.Flag("file", "Config file").Short('f').Required().String()
	hostname     = kingpin.Flag("hostname", "Hostname").Short('h').String()
	ipaddr       = kingpin.Flag("ipaddr", "IP Address").String()
	ignoreErrors = kingpin.Flag("ignore-errors", "Ignore errors").Bool()
	host         = kingpin.Command("host", "Operate host")
	// host status
	hostStatus = host.Command("status", "Operate host status")
	// host status enable
	hostStatusEnable = hostStatus.Command("enable", "Enable host status")
	// host status disable
	hostStatusDisable = hostStatus.Command("disable", "Disable Host status")
	// host register
	hostRegister = host.Command("register", "Regist host")
	// host delete
	hostDelete = host.Command("delete", "Delete host")
	// host list
	hostList = host.Command("list", "Host list")
)

func main() {
	var err error
	kingpin.Version("0.1.1")
	subcommand := kingpin.Parse()

	log := logrus.New()

	var config Config
	config, err = LoadYAML(*file, *hostname)
	if err != nil {
		log.Fatal(err)
	}

	var consul Consul
	consul, err = NewConsul()
	if err != nil {
		log.Fatal(err)
	}

	var storage Storage
	storage, err = NewStorage(config.DBPath, config.DBPerm)
	if err != nil {
		log.Fatal(err)
	}
	defer storage.Close()

	zabbix := NewZabbix(config, consul, storage)

	err = zabbix.APILogin()
	if err != nil {
		log.Fatal(err)
	}

	switch subcommand {
	case "host status enable":
		host, err := zabbix.HostGetByHost()
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
		err = zabbix.HostEnable(host.HostId)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host status disable":
		host, err := zabbix.HostGetByHost()
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
		err = zabbix.HostDisable(host.HostId)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host register":
		ipaddr, err := GetIP(*ipaddr)
		if err != nil {
			log.Fatal(err)
		}

		interfaces := zabbix.HostInterface("", ipaddr, 1, 1, 1)

		groups, err := zabbix.HostGroupIds(config.HostGroups)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}

		templates, err := zabbix.Templates(config.Templates)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}

		err = zabbix.HostCreate(config.Hostname, groups, interfaces, templates)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host delete":
		host, err := zabbix.HostGetByHost()
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
		err = zabbix.HostDelete(host.HostId)
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}
	case "host list":
		zabbixHosts, err := zabbix.EnableHosts()
		if err != nil && !*ignoreErrors {
			log.Fatal(err)
		}

		for _, zHost := range zabbixHosts {
			fmt.Println(zHost.Hostname, zHost.IPAddr)
		}
	case "host proxy":
	}
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "time"
  "os"
  "bufio"
  "log"
  "regexp"
  "errors"
  "math/rand"
)

type Posicao struct {
  linha  int
  coluna int
}

type PacGo struct {
  posicao Posicao
  figura  string // emoji
  pilula  bool
  pontos int
}

type Fantasma struct {
  posicao Posicao
  figura  string // emoji
}

type Labirinto struct {
  largura int
  altura  int
  mapa    []string
  figura string
}

type Movimento int

const (
        Cima = iota
        Baixo
        Esquerda
        Direita
        Nenhum
        Sai
)

var labirinto *Labirinto
var pacgo     *PacGo
var lista_de_fantasmas []*Fantasma
var mapaSinais map[int]string

func construirLabirinto(nomeArquivo string) (*Labirinto, *PacGo, []*Fantasma, error) {

  var ErrMapNotFound = errors.New("Não conseguiu ler o arquivo do mapa")

  var arquivo string
  if nomeArquivo == "" {
    arquivo = "./data/mapa.txt"
  } else {
    arquivo = nomeArquivo
  }

  if file, err := os.Open(arquivo); err == nil {

    // fecha depois de ler o arquivo
    defer file.Close()

    // inicializa o mapa vazio
    var pacgo *PacGo
    fantasmas := []*Fantasma{}
    mapa := []string{}

    r, _ := regexp.Compile("[^ #.]")

    // cria um leitor para ler linha a linha o arquivo
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
      linha := scanner.Text()

      for indice , caracter := range linha {
        switch caracter {
          case 'F': {
            fantasma := &Fantasma{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x91\xBB"}
            fantasmas = append(fantasmas, fantasma)
          }
          case 'G': pacgo = &PacGo{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x98\x83", pontos : 0 }
        }
      }

      linha = r.ReplaceAllString(linha, " ")
      mapa = append(mapa, linha)
    }

    // verifica se teve erro o leitor
    if err = scanner.Err(); err != nil {
      log.Fatal(err)
      return nil, nil, nil, ErrMapNotFound
    }

    l := &Labirinto{largura: len(mapa[0]), altura: len(mapa), mapa : mapa, figura: "\x1b[44m \x1b[0m"}
    return l, pacgo, fantasmas, nil

  } else {
    log.Fatal(err)
    return nil, nil, nil, ErrMapNotFound
  }
}

func atualizarLabirinto() {
  limpaTela()

  // Imprime os pontos
  moveCursor(Posicao{0,0})
  fmt.Printf("%sPontos: %d%s\n", "\x1b[31;1m", pacgo.pontos, "\x1b[0m")

  posicaoInicial := Posicao{2,0}
  moveCursor(posicaoInicial)
  for _, linha := range labirinto.mapa {
    for _, char := range linha {
      switch char {
        case '#': fmt.Print(labirinto.figura)
        case '.': fmt.Print(".")
        default:  fmt.Print(" ")
      }
    }
    fmt.Println("")
  }

  // Imprime PacGo
  moveCursor(posicaoInicial.adiciona(&pacgo.posicao))
  fmt.Printf("%s", pacgo.figura)

  // Imprime fantasmas
  for _, fantasma := range lista_de_fantasmas {
    moveCursor(posicaoInicial.adiciona(&fantasma.posicao))
    fmt.Printf("%s", fantasma.figura)
  }

  // Move o cursor para fora do labirinto
  moveCursor(posicaoInicial.adiciona(&Posicao{labirinto.altura + 2, 0}))
}

func detectarColisao() bool {
  for _, fantasma := range lista_de_fantasmas {
    if fantasma.posicao == pacgo.posicao {
      return true
    }
  }
  return false
}

func moverPacGo(m Movimento) {
  var novaLinha = pacgo.posicao.linha
  var novaColuna = pacgo.posicao.coluna

  switch m {
    case Cima:
      novaLinha--
      if novaLinha < 0 {
        novaLinha = labirinto.altura - 1
      }
    case Baixo:
      novaLinha++
      if novaLinha >= labirinto.altura {
        novaLinha = 0
      }
    case Direita:
      novaColuna++
      if novaColuna >= labirinto.largura {
        novaColuna = 0
      }
    case Esquerda:
      novaColuna--
      if novaColuna < 0 {
        novaColuna = labirinto.largura - 1
      }
  }

  conteudoDoMapa := labirinto.mapa[novaLinha][novaColuna]
  if conteudoDoMapa != '#' {
    pacgo.posicao.linha = novaLinha
    pacgo.posicao.coluna = novaColuna

    if conteudoDoMapa == '.' {
      pacgo.pontos += 10
      linha := labirinto.mapa[novaLinha]
      linha = linha[:novaColuna] + " " + linha[novaColuna+1:]
      labirinto.mapa[novaLinha] = linha
    }
  }
}

func random(min, max int) int {
    return rand.Intn(max - min) + min
}

func move(fantasma *Fantasma, valorDaPosicaoAtualDoFantasma byte, linhaAtualDoFantasma int, colunaAtualDoFantasma int){

  var direcao = random(0, 4)
  var sinal = mapaSinais[direcao]
  //fmt.Println(sinal)
  switch sinal {
  case "Cima":
              if linhaAtualDoFantasma == 0{
                if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = labirinto.altura - 1
                 }
             }else{
               var posicaoAcimaDoFantasma = labirinto.mapa[fantasma.posicao.linha - 1][fantasma.posicao.coluna]
               if posicaoAcimaDoFantasma != '#'{
                 fantasma.posicao.linha = fantasma.posicao.linha - 1
               }
             }
  case "Baixo":
              if linhaAtualDoFantasma == labirinto.altura - 1{
                 if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = 0
                 }
              }else{
                var posicaoAbaixoDoFantasma = labirinto.mapa[fantasma.posicao.linha + 1][fantasma.posicao.coluna]
                if posicaoAbaixoDoFantasma != '#'{
                  fantasma.posicao.linha = fantasma.posicao.linha + 1
                }
              }
  case "Direita":
                if colunaAtualDoFantasma == labirinto.largura-1{
                  if valorDaPosicaoAtualDoFantasma == ' '{
                    fantasma.posicao.coluna = 0
                  }
                }else{
                  var posicaoDireitaDofantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna + 1]
                  if posicaoDireitaDofantasma != '#'{
                    fantasma.posicao.coluna = fantasma.posicao.coluna + 1
                  }
                }
  case "Esquerda":
                 if colunaAtualDoFantasma == 0{
                   if valorDaPosicaoAtualDoFantasma == ' '{
                     fantasma.posicao.coluna = labirinto.largura - 1
                   }
                 }else{
                   var posicaoEsquerdaDoFantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna - 1]
                   if posicaoEsquerdaDoFantasma != '#'{
                     fantasma.posicao.coluna = fantasma.posicao.coluna - 1
                   }
                 }
  }
}

func moverFantasmas() {

  for {
    for i := 0; i < len(lista_de_fantasmas); i++{
        var valorDaPosicaoAtualDoFantasma = labirinto.mapa[lista_de_fantasmas[i].posicao.linha][lista_de_fantasmas[i].posicao.coluna]
        var linhaAtualDoFantasma = lista_de_fantasmas[i].posicao.linha
        var colunaAtualDoFantasma = lista_de_fantasmas[i].posicao.coluna
        //fmt.Println(valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
        move(lista_de_fantasmas[i], valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
    }
    dorme(200)
  }
}

func dorme(milisegundos time.Duration) {
  time.Sleep(time.Millisecond * milisegundos)
}

func entradaDoUsuario(canal chan<- Movimento) {
  array := make([]byte, 10)

  for {
    lido, _ := os.Stdin.Read(array)

    if lido == 1 && array[0] == 0x1b {
      canal <- Sai;
    } else if lido == 3 {
      if array[0] == 0x1b && array[1] == '[' {
        switch array[2] {
        case 'A': canal <- Cima
        case 'B': canal <- Baixo
        case 'C': canal <- Direita
        case 'D': canal <- Esquerda
        }
      }
    }
  }
}

func ativarPilula() {
  pacgo.pilula = true
  go desativarPilula(3000)
}

func desativarPilula(milisegundos time.Duration) {
  dorme(milisegundos)
  pacgo.pilula = false
}

func terminarJogo() {
  // pacgo morreu :(
  moveCursor( Posicao{labirinto.altura + 2, 0} )
  fmt.Println("Fim de jogo! Os fantasmas venceram... \xF0\x9F\x98\xAD")
}

func main() {
  inicializa()
  defer finaliza()

  mapaSinais = make(map[int]string)
  mapaSinais[0] = "Cima"
  mapaSinais[1] = "Baixo"
  mapaSinais[2] = "Direita"
  mapaSinais[3] = "Esquerda"

  args    := os.Args[1:]
  var arquivo string
  if len(args) >= 1 {
    arquivo = args[0]
  } else {
    arquivo = ""
  }

  labirinto, pacgo, lista_de_fantasmas, _ = construirLabirinto(arquivo)

  canal := make(chan Movimento, 10)

  // Processos assincronos
  go entradaDoUsuario(canal)
  go moverFantasmas()

  var tecla Movimento
  for  {
    atualizarLabirinto()

    // canal não-bloqueador
    select {
    case tecla = <-canal:
        moverPacGo(tecla)
    default:
    }
    if tecla == Sai { break }

    if detectarColisao() {
      terminarJogo()
      break;
    }

    dorme(100)
  }
}
<commit_msg>Muda caractere de pílula<commit_after>package main

import (
  "fmt"
  "time"
  "os"
  "bufio"
  "log"
  "regexp"
  "errors"
  "math/rand"
)

type Posicao struct {
  linha  int
  coluna int
}

type PacGo struct {
  posicao Posicao
  figura  string // emoji
  pilula  bool
  pontos int
}

type Fantasma struct {
  posicao Posicao
  figura  string // emoji
}

type Labirinto struct {
  largura int
  altura  int
  mapa    []string
  figura string
}

type Movimento int

const (
        Cima = iota
        Baixo
        Esquerda
        Direita
        Nenhum
        Sai
)

var labirinto *Labirinto
var pacgo     *PacGo
var lista_de_fantasmas []*Fantasma
var mapaSinais map[int]string

func construirLabirinto(nomeArquivo string) (*Labirinto, *PacGo, []*Fantasma, error) {

  var ErrMapNotFound = errors.New("Não conseguiu ler o arquivo do mapa")

  var arquivo string
  if nomeArquivo == "" {
    arquivo = "./data/mapa.txt"
  } else {
    arquivo = nomeArquivo
  }

  if file, err := os.Open(arquivo); err == nil {

    // fecha depois de ler o arquivo
    defer file.Close()

    // inicializa o mapa vazio
    var pacgo *PacGo
    fantasmas := []*Fantasma{}
    mapa := []string{}

    r, _ := regexp.Compile("[^ #.]")

    // cria um leitor para ler linha a linha o arquivo
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
      linha := scanner.Text()

      for indice , caracter := range linha {
        switch caracter {
          case 'F': {
            fantasma := &Fantasma{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x91\xBB"}
            fantasmas = append(fantasmas, fantasma)
          }
          case 'G': pacgo = &PacGo{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x98\x83", pontos : 0 }
        }
      }

      linha = r.ReplaceAllString(linha, " ")
      mapa = append(mapa, linha)
    }

    // verifica se teve erro o leitor
    if err = scanner.Err(); err != nil {
      log.Fatal(err)
      return nil, nil, nil, ErrMapNotFound
    }

    l := &Labirinto{largura: len(mapa[0]), altura: len(mapa), mapa : mapa, figura: "\x1b[44m \x1b[0m"}
    return l, pacgo, fantasmas, nil

  } else {
    log.Fatal(err)
    return nil, nil, nil, ErrMapNotFound
  }
}

func atualizarLabirinto() {
  limpaTela()

  // Imprime os pontos
  moveCursor(Posicao{0,0})
  fmt.Printf("%sPontos: %d%s\n", "\x1b[31;1m", pacgo.pontos, "\x1b[0m")

  posicaoInicial := Posicao{2,0}
  moveCursor(posicaoInicial)
  for _, linha := range labirinto.mapa {
    for _, char := range linha {
      switch char {
        case '#': fmt.Print(labirinto.figura)
        case '.': fmt.Print("·")
        default:  fmt.Print(" ")
      }
    }
    fmt.Println("")
  }

  // Imprime PacGo
  moveCursor(posicaoInicial.adiciona(&pacgo.posicao))
  fmt.Printf("%s", pacgo.figura)

  // Imprime fantasmas
  for _, fantasma := range lista_de_fantasmas {
    moveCursor(posicaoInicial.adiciona(&fantasma.posicao))
    fmt.Printf("%s", fantasma.figura)
  }

  // Move o cursor para fora do labirinto
  moveCursor(posicaoInicial.adiciona(&Posicao{labirinto.altura + 2, 0}))
}

func detectarColisao() bool {
  for _, fantasma := range lista_de_fantasmas {
    if fantasma.posicao == pacgo.posicao {
      return true
    }
  }
  return false
}

func moverPacGo(m Movimento) {
  var novaLinha = pacgo.posicao.linha
  var novaColuna = pacgo.posicao.coluna

  switch m {
    case Cima:
      novaLinha--
      if novaLinha < 0 {
        novaLinha = labirinto.altura - 1
      }
    case Baixo:
      novaLinha++
      if novaLinha >= labirinto.altura {
        novaLinha = 0
      }
    case Direita:
      novaColuna++
      if novaColuna >= labirinto.largura {
        novaColuna = 0
      }
    case Esquerda:
      novaColuna--
      if novaColuna < 0 {
        novaColuna = labirinto.largura - 1
      }
  }

  conteudoDoMapa := labirinto.mapa[novaLinha][novaColuna]
  if conteudoDoMapa != '#' {
    pacgo.posicao.linha = novaLinha
    pacgo.posicao.coluna = novaColuna

    if conteudoDoMapa == '.' {
      pacgo.pontos += 10
      linha := labirinto.mapa[novaLinha]
      linha = linha[:novaColuna] + " " + linha[novaColuna+1:]
      labirinto.mapa[novaLinha] = linha
    }
  }
}

func random(min, max int) int {
    return rand.Intn(max - min) + min
}

func move(fantasma *Fantasma, valorDaPosicaoAtualDoFantasma byte, linhaAtualDoFantasma int, colunaAtualDoFantasma int){

  var direcao = random(0, 4)
  var sinal = mapaSinais[direcao]
  //fmt.Println(sinal)
  switch sinal {
  case "Cima":
              if linhaAtualDoFantasma == 0{
                if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = labirinto.altura - 1
                 }
             }else{
               var posicaoAcimaDoFantasma = labirinto.mapa[fantasma.posicao.linha - 1][fantasma.posicao.coluna]
               if posicaoAcimaDoFantasma != '#'{
                 fantasma.posicao.linha = fantasma.posicao.linha - 1
               }
             }
  case "Baixo":
              if linhaAtualDoFantasma == labirinto.altura - 1{
                 if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = 0
                 }
              }else{
                var posicaoAbaixoDoFantasma = labirinto.mapa[fantasma.posicao.linha + 1][fantasma.posicao.coluna]
                if posicaoAbaixoDoFantasma != '#'{
                  fantasma.posicao.linha = fantasma.posicao.linha + 1
                }
              }
  case "Direita":
                if colunaAtualDoFantasma == labirinto.largura-1{
                  if valorDaPosicaoAtualDoFantasma == ' '{
                    fantasma.posicao.coluna = 0
                  }
                }else{
                  var posicaoDireitaDofantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna + 1]
                  if posicaoDireitaDofantasma != '#'{
                    fantasma.posicao.coluna = fantasma.posicao.coluna + 1
                  }
                }
  case "Esquerda":
                 if colunaAtualDoFantasma == 0{
                   if valorDaPosicaoAtualDoFantasma == ' '{
                     fantasma.posicao.coluna = labirinto.largura - 1
                   }
                 }else{
                   var posicaoEsquerdaDoFantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna - 1]
                   if posicaoEsquerdaDoFantasma != '#'{
                     fantasma.posicao.coluna = fantasma.posicao.coluna - 1
                   }
                 }
  }
}

func moverFantasmas() {

  for {
    for i := 0; i < len(lista_de_fantasmas); i++{
        var valorDaPosicaoAtualDoFantasma = labirinto.mapa[lista_de_fantasmas[i].posicao.linha][lista_de_fantasmas[i].posicao.coluna]
        var linhaAtualDoFantasma = lista_de_fantasmas[i].posicao.linha
        var colunaAtualDoFantasma = lista_de_fantasmas[i].posicao.coluna
        //fmt.Println(valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
        move(lista_de_fantasmas[i], valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
    }
    dorme(200)
  }
}

func dorme(milisegundos time.Duration) {
  time.Sleep(time.Millisecond * milisegundos)
}

func entradaDoUsuario(canal chan<- Movimento) {
  array := make([]byte, 10)

  for {
    lido, _ := os.Stdin.Read(array)

    if lido == 1 && array[0] == 0x1b {
      canal <- Sai;
    } else if lido == 3 {
      if array[0] == 0x1b && array[1] == '[' {
        switch array[2] {
        case 'A': canal <- Cima
        case 'B': canal <- Baixo
        case 'C': canal <- Direita
        case 'D': canal <- Esquerda
        }
      }
    }
  }
}

func ativarPilula() {
  pacgo.pilula = true
  go desativarPilula(3000)
}

func desativarPilula(milisegundos time.Duration) {
  dorme(milisegundos)
  pacgo.pilula = false
}

func terminarJogo() {
  // pacgo morreu :(
  moveCursor( Posicao{labirinto.altura + 2, 0} )
  fmt.Println("Fim de jogo! Os fantasmas venceram... \xF0\x9F\x98\xAD")
}

func main() {
  inicializa()
  defer finaliza()

  mapaSinais = make(map[int]string)
  mapaSinais[0] = "Cima"
  mapaSinais[1] = "Baixo"
  mapaSinais[2] = "Direita"
  mapaSinais[3] = "Esquerda"

  args    := os.Args[1:]
  var arquivo string
  if len(args) >= 1 {
    arquivo = args[0]
  } else {
    arquivo = ""
  }

  labirinto, pacgo, lista_de_fantasmas, _ = construirLabirinto(arquivo)

  canal := make(chan Movimento, 10)

  // Processos assincronos
  go entradaDoUsuario(canal)
  go moverFantasmas()

  var tecla Movimento
  for  {
    atualizarLabirinto()

    // canal não-bloqueador
    select {
    case tecla = <-canal:
        moverPacGo(tecla)
    default:
    }
    if tecla == Sai { break }

    if detectarColisao() {
      terminarJogo()
      break;
    }

    dorme(100)
  }
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/go-chat-bot/bot/slack"
	"os"
)

const (
	slackTokenLabel    string = "KUBEBOT_SLACK_TOKEN"
	slackChannelsLabel string = "KUBEBOT_SLACK_CHANNELS_IDS"
	slackAdminsLabel   string = "KUBEBOT_SLACK_ADMINS_NICKNAMES"
	slackCommandsLabel string = "KUBEBOT_SLACK_VALID_COMMANDS"
)

var (
	kb *Kubebot
)

func main() {
	kb = &Kubebot{
		token:    os.Getenv(slackTokenLabel),
		admins:   stringToMap(os.Getenv(slackAdminsLabel), " "),
		channels: stringToMap(os.Getenv(slackChannelsLabel), " "),
		commands: stringToMap(os.Getenv(slackCommandsLabel), " "),
	}

	slack.Run(kb.token)
}
<commit_msg>Added env variables validation<commit_after>package main

import (
	"errors"
	"fmt"
	"os"

	"github.com/go-chat-bot/bot/slack"
)

const (
	slackTokenLabel    string = "KUBEBOT_SLACK_TOKEN"
	slackChannelsLabel string = "KUBEBOT_SLACK_CHANNELS_IDS"
	slackAdminsLabel   string = "KUBEBOT_SLACK_ADMINS_NICKNAMES"
	slackCommandsLabel string = "KUBEBOT_SLACK_VALID_COMMANDS"
)

var (
	kb *Kubebot
)

func validateEnvParams() error {
	if os.Getenv(slackTokenLabel) == "" {
		return errors.New("slackTokenLabel env variable not defined")
	}
	if os.Getenv(slackChannelsLabel) == "" {
		return errors.New("slackChannelsLabel env variable not defined")
	}
	if os.Getenv(slackAdminsLabel) == "" {
		return errors.New("slackAdminsLabel env variable not defined")
	}
	if os.Getenv(slackCommandsLabel) == "" {
		return errors.New("slackCommandsLabel env variable not defined")
	}

	return nil
}

func main() {

	if err := validateEnvParams(); err != nil {
		fmt.Printf("Kubebot cannot run. Error: %s\n", err.Error())
		return
	}

	kb = &Kubebot{
		token:    os.Getenv(slackTokenLabel),
		admins:   stringToMap(os.Getenv(slackAdminsLabel), " "),
		channels: stringToMap(os.Getenv(slackChannelsLabel), " "),
		commands: stringToMap(os.Getenv(slackCommandsLabel), " "),
	}

	slack.Run(kb.token)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"

	"github.com/urfave/cli"
)

const (
	banner = `
 _____ _____ _____
|   __|  _  |  _  |___ ___ ___
|__   |   __|     |  _| . | -_|
|_____|__|  |__|__|_| |_  |___| %s
                      |___|
Single Page Application server  ________
_______________________________/__\__\__\
                               \__/__/__/

`
)

// version set by LDFLAGS
var version string

func start(root string, port int, redirectHttps bool, logFormat string) {
	e := echo.New()
	e.HideBanner = true

	e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Format: logFormat,
	}))

	if redirectHttps {
		e.Pre(middleware.HTTPSRedirect())
	}

	e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
		Root:   root,
		Index:  "index.html",
		HTML5:  true,
		Browse: false,
	}))

	fmt.Printf(banner, "v"+version)
	fmt.Printf("» http server started on port %d\n", port)

	e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", port)))
}

func main() {
	app := cli.NewApp()
	app.Name = "sparge"
	app.Usage = "A SPA (single-page application) server"
	app.Version = version

	app.Flags = []cli.Flag{}

	app.Commands = []cli.Command{
		{
			Name:  "start",
			Usage: "Start the SPA server",
			Action: func(c *cli.Context) error {
				start(c.String("dir"), c.Int("port"), c.Bool("https-redirect"), c.String("log-format")+"\n")
				return nil
			},
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:   "dir, d",
					Value:  "./public",
					Usage:  "Directory from which to serve files.",
					EnvVar: "SPARGE_DIR",
				},
				cli.StringFlag{
					Name:   "port, p",
					Value:  "8080",
					Usage:  "Server port.",
					EnvVar: "SPARGE_PORT",
				},
				cli.BoolFlag{
					Name:   "https-redirect",
					Usage:  "Use to force http to redirect to https",
					EnvVar: "SPARGE_HTTPS_REDIRECT",
				},
				cli.StringFlag{
					Name: "log-format",
					Value: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}","host":"${host}",` +
						`"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` +
						`"latency_human":"${latency_human}","bytes_in":${bytes_in},` +
						`"bytes_out":${bytes_out}}`,
					Usage:  "Specify the log format",
					EnvVar: "SPARGE_LOG_FORMAT",
				},
			},
		},
	}

	// start()
	app.Run(os.Args)
}
<commit_msg>add idleTimeout<commit_after>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"

	"github.com/urfave/cli"
)

const (
	banner = `
 _____ _____ _____
|   __|  _  |  _  |___ ___ ___
|__   |   __|     |  _| . | -_|
|_____|__|  |__|__|_| |_  |___| %s
                      |___|
Single Page Application server  ________
_______________________________/__\__\__\
                               \__/__/__/

`
	timeout = "620s"
)

// version set by LDFLAGS
var version string

func start(root string, port int, redirectHttps bool, logFormat string) {
	e := echo.New()
	e.HideBanner = true

	e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Format: logFormat,
	}))

	if redirectHttps {
		e.Pre(middleware.HTTPSRedirect())
	}

	e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
		Root:   root,
		Index:  "index.html",
		HTML5:  true,
		Browse: false,
	}))
	timeOut, _ := time.ParseDuration("620s")
	e.Server.IdleTimeout = timeOut

	fmt.Printf(banner, "v"+version)
	fmt.Printf("» http server started on port %d\n", port)

	e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", port)))
}

func main() {
	app := cli.NewApp()
	app.Name = "sparge"
	app.Usage = "A SPA (single-page application) server"
	app.Version = version

	app.Flags = []cli.Flag{}

	app.Commands = []cli.Command{
		{
			Name:  "start",
			Usage: "Start the SPA server",
			Action: func(c *cli.Context) error {
				start(c.String("dir"), c.Int("port"), c.Bool("https-redirect"), c.String("log-format")+"\n")
				return nil
			},
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:   "dir, d",
					Value:  "./public",
					Usage:  "Directory from which to serve files.",
					EnvVar: "SPARGE_DIR",
				},
				cli.StringFlag{
					Name:   "port, p",
					Value:  "8080",
					Usage:  "Server port.",
					EnvVar: "SPARGE_PORT",
				},
				cli.BoolFlag{
					Name:   "https-redirect",
					Usage:  "Use to force http to redirect to https",
					EnvVar: "SPARGE_HTTPS_REDIRECT",
				},
				cli.StringFlag{
					Name: "log-format",
					Value: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}","host":"${host}",` +
						`"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` +
						`"latency_human":"${latency_human}","bytes_in":${bytes_in},` +
						`"bytes_out":${bytes_out}}`,
					Usage:  "Specify the log format",
					EnvVar: "SPARGE_LOG_FORMAT",
				},
			},
		},
	}

	// start()
	app.Run(os.Args)
}
<|endoftext|>