<commit_before>package main

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

	"github.com/deiwin/luncher-api/db"
	"github.com/deiwin/luncher-api/facebook"
	"github.com/deiwin/luncher-api/handler"
	"github.com/deiwin/luncher-api/session"
	"github.com/gorilla/mux"
)

func main() {
	dbConfig := db.NewConfig()
	dbClient := db.NewClient(dbConfig)
	err := dbClient.Connect()
	if err != nil {
		panic(err)
	}
	defer dbClient.Disconnect()

	usersCollection := db.NewUsers(dbClient)
	offersCollection := db.NewOffers(dbClient)
	tagsCollection := db.NewTags(dbClient)

	sessionManager := session.NewManager()
	mainConfig, err := NewConfig()
	if err != nil {
		panic(err)
	}

	facebookConfig := facebook.NewConfig()
	facebookAuthenticator := facebook.NewAuthenticator(facebookConfig, mainConfig.Domain)
	facebookAPI := facebook.NewAPI(facebookConfig)
	facebookHandler := handler.NewFacebook(facebookAuthenticator, sessionManager, facebookAPI, usersCollection)

	r := mux.NewRouter().PathPrefix("/api/v1").Subrouter()
	r.Handle("/offers", handler.Offers(offersCollection))
	r.Handle("/tags", handler.Tags(tagsCollection))
	r.Handle("/login/facebook", facebookHandler.Login())
	r.Handle("/login/facebook/redirected", facebookHandler.Redirected())
	http.Handle("/", r)
	portString := fmt.Sprintf(":%d", mainConfig.Port)
	log.Fatal(http.ListenAndServe(portString, nil))
}
<commit_msg>add slash suffix to subrouter's path prefix<commit_after>package main

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

	"github.com/deiwin/luncher-api/db"
	"github.com/deiwin/luncher-api/facebook"
	"github.com/deiwin/luncher-api/handler"
	"github.com/deiwin/luncher-api/session"
	"github.com/gorilla/mux"
)

func main() {
	dbConfig := db.NewConfig()
	dbClient := db.NewClient(dbConfig)
	err := dbClient.Connect()
	if err != nil {
		panic(err)
	}
	defer dbClient.Disconnect()

	usersCollection := db.NewUsers(dbClient)
	offersCollection := db.NewOffers(dbClient)
	tagsCollection := db.NewTags(dbClient)

	sessionManager := session.NewManager()
	mainConfig, err := NewConfig()
	if err != nil {
		panic(err)
	}

	facebookConfig := facebook.NewConfig()
	facebookAuthenticator := facebook.NewAuthenticator(facebookConfig, mainConfig.Domain)
	facebookAPI := facebook.NewAPI(facebookConfig)
	facebookHandler := handler.NewFacebook(facebookAuthenticator, sessionManager, facebookAPI, usersCollection)

	r := mux.NewRouter().PathPrefix("/api/v1/").Subrouter()
	r.Handle("/offers", handler.Offers(offersCollection))
	r.Handle("/tags", handler.Tags(tagsCollection))
	r.Handle("/login/facebook", facebookHandler.Login())
	r.Handle("/login/facebook/redirected", facebookHandler.Redirected())
	http.Handle("/", r)
	portString := fmt.Sprintf(":%d", mainConfig.Port)
	log.Fatal(http.ListenAndServe(portString, nil))
}
<|endoftext|>


<commit_before>package main

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

	"github.com/CotaPreco/Horus/command"
	"github.com/CotaPreco/Horus/receiver/udp"
	"github.com/CotaPreco/Horus/util"
	"github.com/CotaPreco/Horus/ws"
	wsc "github.com/CotaPreco/Horus/ws/command"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// @link https://godoc.org/github.com/gorilla/websocket#hdr-Origin_Considerations
		return true
	},
}

var (
	VERSION   = "N/A"
	GITCOMMIT = "N/A"
)

var (
	defaultWsHost           = util.EnvOrDefault("WS_HOST", "0.0.0.0")
	defaultWsPort           = util.EnvOrDefault("WS_PORT", "8000")
	defaultUdpReceiverHost  = util.EnvOrDefault("UDP_RECEIVER_HOST", "0.0.0.0")
	defaultUdpReceiverPort  = util.EnvOrDefault("UDP_RECEIVER_PORT", "7600")
	defaultUdpMaxPacketSize = util.EnvOrDefault("UDP_PACKET_SIZE", "8192")
)

var (
	flgVersion    = flag.Bool("v", false, "")
	udpHost       = flag.String("receiver-udp-host", defaultUdpReceiverHost, "")
	udpPort       = flag.Int("receiver-udp-port", util.Str2int(defaultUdpReceiverPort), "")
	wsHost        = flag.String("ws-host", defaultWsHost, "")
	wsPort        = flag.Int("ws-port", util.Str2int(defaultWsPort), "")
	udpPacketSize = flag.Int("udp-max-packet-size", util.Str2int(defaultUdpMaxPacketSize), "")
)

func main() {
	flag.Usage = func() {
		flag.CommandLine.SetOutput(os.Stdout)

		var help = strings.Trim(`
Horus — A simple and minimalist event-hub for pipelining events :-)

USAGE:
	horus [...OPTIONS]

OPTIONS:
%s
`, "\n")

		var opts string

		for _, opt := range [][]string{
			{
				"-v",
				"Prints the current version of `Horus`",
			}, {
				"-ws-host",
				"Defines in which IP WebSocket will bind to",
			}, {
				"-ws-port",
				"Defines the port for the WebSocket server listen for connections",
			}, {
				"-receiver-udp-host",
				"Defines in which IP the UDP receiver will bind to",
			}, {
				"-receiver-udp-port",
				"Defines the port for receiver listen on",
			}, {
				"-udp-max-packet-size",
				"Defines the maximum buffer size for packet",
			},
		} {
			opts += fmt.Sprintf("\t%-25.20s /* %s */\n", opt[0], opt[1])
		}

		fmt.Printf(help, opts)

		os.Exit(0)
	}

	flag.Parse()

	if *flgVersion {
		fmt.Printf("Horus v%s, build %s\n", VERSION, GITCOMMIT)
		return
	}

	// --
	bus := command.NewGenericCommandBus()
	hub := ws.NewTaggedConnectionHub()

	bus.PushHandler(hub)
	bus.PushHandler(wsc.NewARTagCommandRedispatcher(bus))

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		conn, err := upgrader.Upgrade(w, r, nil)

		if err != nil {
			return
		}

		defer conn.Close()

		hub.Subscribe(conn)

		defer hub.Unsubscribe(conn)

		for {
			messageType, message, err := conn.ReadMessage()

			if err != nil {
				return
			}

			if messageType == websocket.TextMessage {
				bus.Dispatch(wsc.NewSimpleTextCommand(string(message), conn))
			}
		}
	})

	// ---
	receiver := udp.NewUdpReceiver(*udpHost, *udpPort, *udpPacketSize, new(udp.NullByteReceiveStrategy))
	receiver.Attach(hub)

	go receiver.Receive()
	// ---

	err := http.ListenAndServe(
		fmt.Sprintf("%s:%d", *wsHost, *wsPort),
		nil,
	)

	util.Invariant(
		err == nil,
		"...unexpected `%s` (ListenAndServe)",
		err,
	)
}
<commit_msg>Fixes #19<commit_after>package main

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

	"github.com/CotaPreco/Horus/command"
	"github.com/CotaPreco/Horus/receiver/udp"
	"github.com/CotaPreco/Horus/util"
	"github.com/CotaPreco/Horus/ws"
	wsc "github.com/CotaPreco/Horus/ws/command"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// @link https://godoc.org/github.com/gorilla/websocket#hdr-Origin_Considerations
		return true
	},
}

var (
	VERSION   = "N/A"
	GITCOMMIT = "N/A"
)

var (
	defaultWsHost           = util.EnvOrDefault("WS_HOST", "0.0.0.0")
	defaultWsPort           = util.EnvOrDefault("WS_PORT", "8000")
	defaultUdpReceiverHost  = util.EnvOrDefault("UDP_RECEIVER_HOST", "0.0.0.0")
	defaultUdpReceiverPort  = util.EnvOrDefault("UDP_RECEIVER_PORT", "7600")
	defaultUdpMaxPacketSize = util.EnvOrDefault("UDP_PACKET_SIZE", "8192")
)

var (
	flgVersion    = flag.Bool("v", false, "")
	udpHost       = flag.String("receiver-udp-host", defaultUdpReceiverHost, "")
	udpPort       = flag.Int("receiver-udp-port", util.Str2int(defaultUdpReceiverPort), "")
	wsHost        = flag.String("ws-host", defaultWsHost, "")
	wsPort        = flag.Int("ws-port", util.Str2int(defaultWsPort), "")
	udpPacketSize = flag.Int("udp-max-packet-size", util.Str2int(defaultUdpMaxPacketSize), "")
)

func main() {
	flag.Usage = func() {
		flag.CommandLine.SetOutput(os.Stdout)

		var help = strings.Trim(`
Horus — A simple and minimalist event-hub for pipelining events :-)

USAGE:
	horus [...OPTIONS]

OPTIONS:
%s
`, "\n")

		var opts string

		for _, opt := range [][]string{
			{
				"-v",
				"Prints the current version of `Horus`",
			}, {
				"-ws-host",
				"Defines in which IP WebSocket will bind to",
			}, {
				"-ws-port",
				"Defines the port for the WebSocket server listen for connections",
			}, {
				"-receiver-udp-host",
				"Defines in which IP the UDP receiver will bind to",
			}, {
				"-receiver-udp-port",
				"Defines the port for receiver listen on",
			}, {
				"-udp-max-packet-size",
				"Defines the maximum buffer size for packet",
			},
		} {
			opts += fmt.Sprintf("\t%-25.20s /* %s */\n", opt[0], opt[1])
		}

		fmt.Printf(help, opts)

		os.Exit(0)
	}

	flag.Parse()

	if *flgVersion {
		fmt.Printf("Horus v%s, build %s\n", VERSION, GITCOMMIT)
		return
	}

	// --
	bus := command.NewGenericCommandBus()
	hub := ws.NewTaggedConnectionHub()

	bus.PushHandler(hub)
	bus.PushHandler(wsc.NewARTagCommandRedispatcher(bus))

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		conn, err := upgrader.Upgrade(w, r, nil)

		if err != nil {
			return
		}

		defer conn.Close()

		hub.Subscribe(conn)

		defer hub.Unsubscribe(conn)

		for {
			messageType, message, err := conn.ReadMessage()

			if err != nil {
				return
			}

			if messageType == websocket.TextMessage {
				bus.Dispatch(wsc.NewSimpleTextCommand(string(message), conn))
			}
		}
	})

	// ---
	receiver := udp.NewUdpReceiver(*udpHost, *udpPort, *udpPacketSize, new(udp.NullByteReceiveStrategy))
	receiver.Attach(hub)

	go receiver.Receive()
	// ---

	fmt.Printf(
		"Udp Receiver — %s:%d\nWebSocket — %s:%d\n",
		*udpHost,
		*udpPort,
		*wsHost,
		*wsPort,
	)

	err := http.ListenAndServe(
		fmt.Sprintf("%s:%d", *wsHost, *wsPort),
		nil,
	)

	util.Invariant(
		err == nil,
		"...unexpected `%s` (ListenAndServe)",
		err,
	)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"

	cointip "github.com/Bullpeen/cointip/quadlek"
	log "github.com/Sirupsen/logrus"
	"github.com/jirwin/quadlek/plugins/echo"
	"github.com/jirwin/quadlek/plugins/karma"
	"github.com/jirwin/quadlek/plugins/nextep"
	"github.com/jirwin/quadlek/plugins/random"
	"github.com/jirwin/quadlek/plugins/spotify"
	"github.com/jirwin/quadlek/plugins/twitter"
	"github.com/jirwin/quadlek/quadlek"

	"github.com/Bullpeen/infobot"
	"github.com/urfave/cli"
)

const Version = "0.0.1"

func run(c *cli.Context) error {
	var apiToken string
	if c.IsSet("api-key") {
		apiToken = c.String("api-key")
	} else {
		cli.ShowAppHelp(c)
		return cli.NewExitError("Missing --api-key arg.", 1)
	}

	var verificationToken string
	if c.IsSet("verification-token") {
		verificationToken = c.String("verification-token")
	} else {
		cli.ShowAppHelp(c)
		return cli.NewExitError("Missing --verification-token arg.", 1)
	}

	dbPath := c.String("db-path")

	bot, err := quadlek.NewBot(context.Background(), apiToken, verificationToken, dbPath)
	if err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Error("error creating bot")
		return nil
	}

	err = bot.RegisterPlugin(echo.Register())
	if err != nil {
		fmt.Printf("error registering echo plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(karma.Register())
	if err != nil {
		fmt.Printf("error registering karma plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(random.Register())
	if err != nil {
		fmt.Printf("error registering random plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(spotify.Register())
	if err != nil {
		fmt.Printf("error registering spotify plugin: %s", err.Error())
		return nil
	}

	if c.IsSet("tvdb-key") {
		tvdbKey := c.String("tvdb-key")

		err = bot.RegisterPlugin(nextep.Register(tvdbKey))
		if err != nil {
			fmt.Printf("error registering nextep plugin: %s", err.Error())
			return nil
		}
	}

	err = bot.RegisterPlugin(infobot.Register())
	if err != nil {
		fmt.Printf("error registering infobot plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(twitter.Register(
		c.String("twitter-consumer-key"),
		c.String("twitter-consumer-secret"),
		c.String("twitter-access-token"),
		c.String("twitter-access-secret"),
		// These must be twitter user ids, not names. https://tweeterid.com/ for easy conversion between the two.
		map[string]string{
			"25073877":           "politics", // @realDonaldTrump
			"822215679726100480"  "politics", // @POTUS
			"778682":             "general",  // @jirwin
			"26786244":           "general",  // @schonstal
			"2317524115":         "general",  // @PHP_CEO
			"120252183":          "random",   // @fakescience
		},
	))

	coinbasePlugin := cointip.Register(
		c.String("coinbase-key"),
		c.String("coinbase-secret"),
		c.String("coinbase-account"),
	)
	if coinbasePlugin != nil {
		err = bot.RegisterPlugin(coinbasePlugin)
		if err != nil {
			panic(err)
		}
	}

	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)

	bot.Start()
	<-signals
	bot.Stop()

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = "quadlek"
	app.Version = Version
	app.Usage = "a slack bot"
	app.Action = run
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "api-key",
			Usage:  "The slack api token for the bot",
			EnvVar: "QUADLEK_API_TOKEN",
		},
		cli.StringFlag{
			Name:   "verification-token",
			Usage:  "The slack webhook verification token.",
			EnvVar: "QUADLEK_VERIFICATION_TOKEN",
		},
		cli.StringFlag{
			Name:   "db-path",
			Usage:  "The path where the database is stored.",
			Value:  "quadlek.db",
			EnvVar: "QUADLEK_DB_PATH",
		},
		cli.StringFlag{
			Name:   "tvdb-key",
			Usage:  "The TVDB api key for the bot, used by the nextep command",
			EnvVar: "QUADLEK_TVDB_TOKEN",
		},
		cli.StringFlag{
			Name:   "twitter-consumer-key",
			Usage:  "The consumer key for the twitter api",
			EnvVar: "QUADLEK_TWITTER_CONSUMER_KEY",
		},
		cli.StringFlag{
			Name:   "twitter-consumer-secret",
			Usage:  "The consumer secret for the twitter api",
			EnvVar: "QUADLEK_TWITTER_CONSUMER_SECRET",
		},
		cli.StringFlag{
			Name:   "twitter-access-token",
			Usage:  "The access key for the twitter api",
			EnvVar: "QUADLEK_TWITTER_ACCESS_TOKEN",
		},
		cli.StringFlag{
			Name:   "twitter-access-secret",
			Usage:  "The access secret for the twitter api",
			EnvVar: "QUADLEK_TWITTER_ACCESS_SECRET",
		},
		cli.StringFlag{
			Name:   "coinbase-key",
			Usage:  "The access key for the coinbase api",
			EnvVar: "QUADLEK_COINBASE_KEY",
		},
		cli.StringFlag{
			Name:   "coinbase-secret",
			Usage:  "The access secret for the coinbase api",
			EnvVar: "QUADLEK_COINBASE_SECRET",
		},
		cli.StringFlag{
			Name:   "coinbase-account",
			Usage:  "The bank account for the coinbase api",
			EnvVar: "QUADLEK_COINBASE_BANK_ACCOUNT",
		},
	}

	app.Run(os.Args)
}
<commit_msg>Fix typo.<commit_after>package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"

	cointip "github.com/Bullpeen/cointip/quadlek"
	log "github.com/Sirupsen/logrus"
	"github.com/jirwin/quadlek/plugins/echo"
	"github.com/jirwin/quadlek/plugins/karma"
	"github.com/jirwin/quadlek/plugins/nextep"
	"github.com/jirwin/quadlek/plugins/random"
	"github.com/jirwin/quadlek/plugins/spotify"
	"github.com/jirwin/quadlek/plugins/twitter"
	"github.com/jirwin/quadlek/quadlek"

	"github.com/Bullpeen/infobot"
	"github.com/urfave/cli"
)

const Version = "0.0.1"

func run(c *cli.Context) error {
	var apiToken string
	if c.IsSet("api-key") {
		apiToken = c.String("api-key")
	} else {
		cli.ShowAppHelp(c)
		return cli.NewExitError("Missing --api-key arg.", 1)
	}

	var verificationToken string
	if c.IsSet("verification-token") {
		verificationToken = c.String("verification-token")
	} else {
		cli.ShowAppHelp(c)
		return cli.NewExitError("Missing --verification-token arg.", 1)
	}

	dbPath := c.String("db-path")

	bot, err := quadlek.NewBot(context.Background(), apiToken, verificationToken, dbPath)
	if err != nil {
		log.WithFields(log.Fields{
			"err": err,
		}).Error("error creating bot")
		return nil
	}

	err = bot.RegisterPlugin(echo.Register())
	if err != nil {
		fmt.Printf("error registering echo plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(karma.Register())
	if err != nil {
		fmt.Printf("error registering karma plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(random.Register())
	if err != nil {
		fmt.Printf("error registering random plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(spotify.Register())
	if err != nil {
		fmt.Printf("error registering spotify plugin: %s", err.Error())
		return nil
	}

	if c.IsSet("tvdb-key") {
		tvdbKey := c.String("tvdb-key")

		err = bot.RegisterPlugin(nextep.Register(tvdbKey))
		if err != nil {
			fmt.Printf("error registering nextep plugin: %s", err.Error())
			return nil
		}
	}

	err = bot.RegisterPlugin(infobot.Register())
	if err != nil {
		fmt.Printf("error registering infobot plugin: %s", err.Error())
		return nil
	}

	err = bot.RegisterPlugin(twitter.Register(
		c.String("twitter-consumer-key"),
		c.String("twitter-consumer-secret"),
		c.String("twitter-access-token"),
		c.String("twitter-access-secret"),
		// These must be twitter user ids, not names. https://tweeterid.com/ for easy conversion between the two.
		map[string]string{
			"25073877":            "politics", // @realDonaldTrump
			"822215679726100480":  "politics", // @POTUS
			"778682":              "general",  // @jirwin
			"26786244":            "general",  // @schonstal
			"2317524115":          "general",  // @PHP_CEO
			"120252183":           "random",   // @fakescience
		},
	))

	coinbasePlugin := cointip.Register(
		c.String("coinbase-key"),
		c.String("coinbase-secret"),
		c.String("coinbase-account"),
	)
	if coinbasePlugin != nil {
		err = bot.RegisterPlugin(coinbasePlugin)
		if err != nil {
			panic(err)
		}
	}

	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)

	bot.Start()
	<-signals
	bot.Stop()

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = "quadlek"
	app.Version = Version
	app.Usage = "a slack bot"
	app.Action = run
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "api-key",
			Usage:  "The slack api token for the bot",
			EnvVar: "QUADLEK_API_TOKEN",
		},
		cli.StringFlag{
			Name:   "verification-token",
			Usage:  "The slack webhook verification token.",
			EnvVar: "QUADLEK_VERIFICATION_TOKEN",
		},
		cli.StringFlag{
			Name:   "db-path",
			Usage:  "The path where the database is stored.",
			Value:  "quadlek.db",
			EnvVar: "QUADLEK_DB_PATH",
		},
		cli.StringFlag{
			Name:   "tvdb-key",
			Usage:  "The TVDB api key for the bot, used by the nextep command",
			EnvVar: "QUADLEK_TVDB_TOKEN",
		},
		cli.StringFlag{
			Name:   "twitter-consumer-key",
			Usage:  "The consumer key for the twitter api",
			EnvVar: "QUADLEK_TWITTER_CONSUMER_KEY",
		},
		cli.StringFlag{
			Name:   "twitter-consumer-secret",
			Usage:  "The consumer secret for the twitter api",
			EnvVar: "QUADLEK_TWITTER_CONSUMER_SECRET",
		},
		cli.StringFlag{
			Name:   "twitter-access-token",
			Usage:  "The access key for the twitter api",
			EnvVar: "QUADLEK_TWITTER_ACCESS_TOKEN",
		},
		cli.StringFlag{
			Name:   "twitter-access-secret",
			Usage:  "The access secret for the twitter api",
			EnvVar: "QUADLEK_TWITTER_ACCESS_SECRET",
		},
		cli.StringFlag{
			Name:   "coinbase-key",
			Usage:  "The access key for the coinbase api",
			EnvVar: "QUADLEK_COINBASE_KEY",
		},
		cli.StringFlag{
			Name:   "coinbase-secret",
			Usage:  "The access secret for the coinbase api",
			EnvVar: "QUADLEK_COINBASE_SECRET",
		},
		cli.StringFlag{
			Name:   "coinbase-account",
			Usage:  "The bank account for the coinbase api",
			EnvVar: "QUADLEK_COINBASE_BANK_ACCOUNT",
		},
	}

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


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/hybridgroup/gobot"
	"github.com/hybridgroup/gobot/platforms/sphero"
)

func main() {
	deviceName := flag.String("device", "", "path to Sphero device")
	flag.Parse()

	gbot := gobot.NewGobot()

	adaptor := sphero.NewSpheroAdaptor("sphero", *deviceName)
	driver := sphero.NewSpheroDriver(adaptor, "sphero")

	work := func() {
		gobot.Every(3*time.Second, func() {
			driver.Roll(30, uint16(gobot.Rand(360)))
		})
	}

	robot := gobot.NewRobot("sphero",
		[]gobot.Connection{adaptor},
		[]gobot.Device{driver},
		work,
	)

	gbot.AddRobot(robot)

	var errors []error
	go func() {
		errors = gbot.Start()
	}()
	if errors != nil {
		gbot.Robot("sphero").Connection("sphero").Finalize()
	}

	// Handle SIGINT and SIGTERM.
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	log.Println(<-ch)

	// Stop the service gracefully.
	log.Println("Shutdown successful, exiting")
}
<commit_msg>Pulls the latest stock price of Google and controls the heading of the Sphero<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/hybridgroup/gobot"
	"github.com/hybridgroup/gobot/platforms/sphero"
)

func main() {
	deviceName := flag.String("device", "", "path to Sphero device")
	flag.Parse()

	gbot := gobot.NewGobot()

	adaptor := sphero.NewSpheroAdaptor("sphero", *deviceName)
	driver := sphero.NewSpheroDriver(adaptor, "sphero")

	work := func() {
		var previousStockPrice float64

		gobot.Every(3*time.Second, func() {
			// retrieve: opening price, last price
			resp, err := http.Get("http://download.finance.yahoo.com/d/quotes.csv?s=GOOG&f=ol1")
			defer resp.Body.Close()
			if err == nil {
				body, _ := ioutil.ReadAll(resp.Body)
				quoteParts := strings.Split(string(body), ",")
				if len(quoteParts) > 1 {
					openingPrice, _ := strconv.ParseFloat(strings.TrimSpace(quoteParts[0]), 32)
					lastPrice, _ := strconv.ParseFloat(strings.TrimSpace(quoteParts[1]), 32)

					// set color based on status of stock
					if lastPrice > openingPrice {
						driver.SetRGB(0, 255, 0) //green
					} else {
						driver.SetRGB(255, 0, 0) //red
					}
					fmt.Printf("Last Price=%f, Opening Price=%f\n", lastPrice, openingPrice)

					// calculate percentage change for the day
					if previousStockPrice == 0.0 {
						previousStockPrice = lastPrice
					}
					percentageChange := uint16(10000 * ((lastPrice - previousStockPrice) / previousStockPrice))
					fmt.Printf("Percentage change: %d\n", percentageChange)

					var heading uint16
					if percentageChange < 0 {
						heading = 360 + percentageChange
					} else {
						heading = percentageChange
					}

					fmt.Printf("Heading: %d\n", heading)
					driver.Roll(100, heading)
					time.Sleep(1 * time.Second)
					driver.Stop()

					previousStockPrice = lastPrice
				}
			}
		})
	}

	robot := gobot.NewRobot("sphero",
		[]gobot.Connection{adaptor},
		[]gobot.Device{driver},
		work,
	)

	gbot.AddRobot(robot)

	var errors []error
	go func() {
		errors = gbot.Start()
	}()
	if errors != nil {
		gbot.Robot("sphero").Connection("sphero").Finalize()
	}

	// Handle SIGINT and SIGTERM.
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
	fmt.Println(<-ch)

	// Stop the service gracefully.
	fmt.Println("Shutdown successful, exiting")
}
<|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"

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

var bot *linebot.Client

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	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) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(  "Line_ID:" + message.ID)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}
<commit_msg>測試UserID<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"

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

var bot *linebot.Client

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	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) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(  "Line_ID:" + UserID)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

func main(){

}<commit_msg>proxy without ssl<commit_after>package main

import (
	"flag"
	"github.com/Sirupsen/logrus"
	"io"
	"net"
	"time"
)

var (
	inPort            = flag.Int("in-port", 1443, "")
	targetPort        = flag.Int("target-port", 80, "")
	targetConnTimeout = flag.Duration("target-conn-timeout", time.Second, "")
)

func main() {
	logrus.SetLevel(logrus.DebugLevel)
	tcpAddr := &net.TCPAddr{}
	tcpAddr.Port = *inPort
	logrus.Errorf("Start listen: %v", tcpAddr)

	listener, err := net.ListenTCP("tcp", tcpAddr)
	logrus.Debug(listener.Addr())
	logrus.Debugf("%#v", listener)
	if err != nil {
		panic(err)
	}
	for {
		tcpConn, err := listener.AcceptTCP()
		if err != nil {
			panic(err)
		}
		go handleTcpConnection(tcpConn)
	}
}

func handleTcpConnection(in *net.TCPConn){
	target, err := getTargetConn(in)
	if err != nil {
		logrus.Errorf("Can't get target IP/port for '%v': %v", target.String(),err)
		return
	}
	startProxy(target, in)
}

func getTargetConn(in *net.TCPConn) (targetAddr net.TCPAddr, err error) {
	targetAddrP, err := net.ResolveTCPAddr("tcp", in.LocalAddr().String())
	if err != nil {
		logrus.Errorf("Can't resolve local addr '%v': %v", in.LocalAddr().String(), err)
		return net.TCPAddr{}, err
	}
	targetAddrP.Port = *targetPort
	return *targetAddrP, nil
}

func startProxy(targetAddr net.TCPAddr, in net.Conn) {
	logrus.Infof("Start proxy connection from '%v' to'%v'", in.RemoteAddr().String(), targetAddr.String())

	targetConnCommon, err := net.DialTimeout("tcp", targetAddr.String(), *targetConnTimeout)
	if err != nil {
		logrus.Warnf("Can't connect to target '%v': %v", targetAddr.String(), err)
		return
	}

	targetConn := targetConnCommon.(*net.TCPConn)
	go func() {
		io.Copy(in, targetConn)
		in.Close()
		targetConn.Close()
	}()
	go func() {
		io.Copy(targetConn, in)
		in.Close()
		targetConn.Close()
	}()
}
<|endoftext|>


<commit_before>package main

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

	"github.com/prometheus/client_golang/prometheus"
)

var errorCounter = prometheus.NewCounter(prometheus.CounterOpts{
	Namespace: "mesos",
	Subsystem: "collector",
	Name:      "errors_total",
	Help:      "Total number of internal mesos-collector errors.",
})

func init() {
	prometheus.MustRegister(errorCounter)
}

func main() {
	fs := flag.NewFlagSet("mesos-exporter", flag.ExitOnError)
	addr := fs.String("addr", ":9110", "Address to listen on")
	masterURL := fs.String("master", "", "Expose metrics from master running on this URL")
	slaveURL := fs.String("slave", "", "Expose metrics from slave running on t his URL")
	timeout := fs.Duration("timeout", 5*time.Second, "Master polling timeout")

	fs.Parse(os.Args[1:])
	if *masterURL != "" && *slaveURL != "" {
		log.Fatal("Only -master or -slave can be given at a time")
	}

	switch {
	case *masterURL != "":
		for _, c := range []prometheus.Collector{
			newMasterCollector(*masterURL, *timeout),
			newMasterStateCollector(*masterURL, *timeout),
		} {
			if err := prometheus.Register(c); err != nil {
				log.Fatal(err)
			}
		}
		log.Printf("Exposing master metrics on %s", *addr)

	case *slaveURL != "":
		for _, c := range []prometheus.Collector{
			newSlaveCollector(*slaveURL, *timeout),
			newSlaveMonitorCollector(*slaveURL, *timeout),
		} {
			if err := prometheus.Register(c); err != nil {
				log.Fatal(err)
			}
		}
		log.Printf("Exposing slave metrics on %s", *addr)

	default:
		log.Fatal("Either -master or -slave is required")
	}

	http.Handle("/metrics", prometheus.Handler())
	if err := http.ListenAndServe(*addr, nil); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add root HTTP handler<commit_after>package main

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

	"github.com/prometheus/client_golang/prometheus"
)

var errorCounter = prometheus.NewCounter(prometheus.CounterOpts{
	Namespace: "mesos",
	Subsystem: "collector",
	Name:      "errors_total",
	Help:      "Total number of internal mesos-collector errors.",
})

func init() {
	prometheus.MustRegister(errorCounter)
}

func main() {
	fs := flag.NewFlagSet("mesos-exporter", flag.ExitOnError)
	addr := fs.String("addr", ":9110", "Address to listen on")
	masterURL := fs.String("master", "", "Expose metrics from master running on this URL")
	slaveURL := fs.String("slave", "", "Expose metrics from slave running on t his URL")
	timeout := fs.Duration("timeout", 5*time.Second, "Master polling timeout")

	fs.Parse(os.Args[1:])
	if *masterURL != "" && *slaveURL != "" {
		log.Fatal("Only -master or -slave can be given at a time")
	}

	switch {
	case *masterURL != "":
		for _, c := range []prometheus.Collector{
			newMasterCollector(*masterURL, *timeout),
			newMasterStateCollector(*masterURL, *timeout),
		} {
			if err := prometheus.Register(c); err != nil {
				log.Fatal(err)
			}
		}
		log.Printf("Exposing master metrics on %s", *addr)

	case *slaveURL != "":
		for _, c := range []prometheus.Collector{
			newSlaveCollector(*slaveURL, *timeout),
			newSlaveMonitorCollector(*slaveURL, *timeout),
		} {
			if err := prometheus.Register(c); err != nil {
				log.Fatal(err)
			}
		}
		log.Printf("Exposing slave metrics on %s", *addr)

	default:
		log.Fatal("Either -master or -slave is required")
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
            <title>Mesos Exporter</title>

Mesos Exporter

Metrics

            `))
	})
	http.Handle("/metrics", prometheus.Handler())
	if err := http.ListenAndServe(*addr, nil); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net"
	"os"
	"strings"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

var (
	logger = logrus.New()

	globalFlags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for the logs",
		},
		cli.StringSliceFlag{
			Name:  "host",
			Value: &cli.StringSlice{},
			Usage: "SSH host address",
		},
		cli.StringFlag{
			Name:  "user,u",
			Value: "root",
			Usage: "user to execute the command as",
		},
		cli.StringFlag{
			Name:  "identity,i",
			Value: "id_rsa",
			Usage: "SSH identity to use for connecting to the host",
		},
		cli.BoolFlag{
			Name:  "agent,A",
			Usage: "Forward authentication request to the ssh agent",
		},
		cli.StringSliceFlag{
			Name:  "env,e",
			Usage: "set environment variables for SSH command",
			Value: &cli.StringSlice{},
		},
		cli.BoolFlag{
			Name:  "quiet,q",
			Usage: "disable output from the ssh command",
		},
	}
)

// preload initializes any global options and configuration
// before the main or sub commands are run
func preload(context *cli.Context) error {
	if context.GlobalBool("debug") {
		logger.Level = logrus.DebugLevel
	}
	return nil
}

// multiplexAction uses the arguments passed via the command line and
// multiplexes them across multiple SSH connections
func multiplexAction(context *cli.Context) {
	c, err := newCommand(context)
	if err != nil {
		logger.Fatal(err)
	}
	logger.Debug(c)

	hosts := []string(context.GlobalStringSlice("host"))
	if len(hosts) == 0 {
		logger.Fatal("no host specified for command to run")
	}
	logger.Debugf("hosts %v", hosts)
	group := &sync.WaitGroup{}
	for _, h := range hosts {
		group.Add(1)
		go executeCommand(c, h, context.GlobalBool("A"), context.GlobalBool("quiet"), group)
	}
	group.Wait()
	logger.Debugf("finished executing %s on all hosts", c)
}

func executeCommand(c command, host string, agentForwarding, quiet bool, group *sync.WaitGroup) {
	defer group.Done()
	var (
		err          error
		originalHost = host
	)

	if host, err = cleanHost(host); err != nil {
		logger.WithField("host", originalHost).Error(err)
		return
	}

	if err = runSSH(c, host, agentForwarding, quiet); err != nil {
		logger.WithField("host", host).Error(err)
		return
	}
	logger.Debugf("host %s executed successfully", host)
}

// runSSH executes the given command on the given host
func runSSH(c command, host string, agentForwarding, quiet bool) error {
	config, err := newSshClientConfig(c.User, c.Identity, agentForwarding)
	if err != nil {
		return err
	}
	session, err := config.NewSession(host)
	if err != nil {
		return err
	}
	defer session.Close()

	// TODO: find a better way to multiplex all the streams
	// and support STDIN without sending to all sessions
	if !quiet {
		session.Stderr = newNameWriter(host, os.Stderr)
		session.Stdout = newNameWriter(host, os.Stdout)
	}
	for key, value := range c.Env {
		if err := session.Setenv(key, value); err != nil {
			return err
		}
	}
	return session.Run(c.Cmd)
}

// cleanHost parses out the hostname/ip and port.  If no port is
// specified then port 22 is appended to the hostname/ip
func cleanHost(host string) (string, error) {
	h, port, err := net.SplitHostPort(host)
	if err != nil {
		if !strings.Contains(err.Error(), "missing port in address") {
			return "", err
		}
		port = "22"
		h = host
	}
	if port == "" {
		port = "22"
	}
	return net.JoinHostPort(h, port), nil
}

func main() {
	app := cli.NewApp()
	app.Name = "slex"
	app.Usage = "SSH commands multiplexed"
	app.Version = "1"
	app.Author = "@crosbymichael"
	app.Email = "crosbymichael@gmail.com"

	app.Before = preload
	app.Flags = globalFlags
	app.Action = multiplexAction

	if err := app.Run(os.Args); err != nil {
		logger.Fatal(err)
	}
}
<commit_msg>Add hosts file for getting host addresses<commit_after>package main

import (
	"bufio"
	"net"
	"os"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

// preload initializes any global options and configuration
// before the main or sub commands are run
func preload(context *cli.Context) error {
	if context.GlobalBool("debug") {
		log.SetLevel(log.DebugLevel)
	}
	return nil
}

// hostHosts returns a list of host addresses that are specified on the
// command line and also in a hosts file separated by new lines.
func loadHosts(context *cli.Context) ([]string, error) {
	hosts := []string(context.GlobalStringSlice("host"))
	if hostsFile := context.GlobalString("hosts"); hostsFile != "" {
		f, err := os.Open(hostsFile)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		s := bufio.NewScanner(f)
		for s.Scan() {
			if err := s.Err(); err != nil {
				return nil, err
			}
			hosts = append(hosts, s.Text())
		}
	}
	return hosts, nil
}

// multiplexAction uses the arguments passed via the command line and
// multiplexes them across multiple SSH connections
func multiplexAction(context *cli.Context) {
	c, err := newCommand(context)
	if err != nil {
		log.Fatal(err)
	}
	log.Debug(c)

	hosts, err := loadHosts(context)
	if err != nil {
		log.Fatal(err)
	}
	if len(hosts) == 0 {
		log.Fatal("no host specified for command to run")
	}
	log.Debugf("hosts %v", hosts)
	group := &sync.WaitGroup{}
	for _, h := range hosts {
		group.Add(1)
		go executeCommand(c, h, context.GlobalBool("A"), context.GlobalBool("quiet"), group)
	}
	group.Wait()
	log.Debugf("finished executing %s on all hosts", c)
}

func executeCommand(c command, host string, agentForwarding, quiet bool, group *sync.WaitGroup) {
	defer group.Done()
	var (
		err          error
		originalHost = host
	)

	if host, err = cleanHost(host); err != nil {
		log.WithField("host", originalHost).Error(err)
		return
	}

	if err = runSSH(c, host, agentForwarding, quiet); err != nil {
		log.WithField("host", host).Error(err)
		return
	}
	log.Debugf("host %s executed successfully", host)
}

// runSSH executes the given command on the given host
func runSSH(c command, host string, agentForwarding, quiet bool) error {
	config, err := newSshClientConfig(c.User, c.Identity, agentForwarding)
	if err != nil {
		return err
	}
	session, err := config.NewSession(host)
	if err != nil {
		return err
	}
	defer session.Close()

	// TODO: find a better way to multiplex all the streams
	// and support STDIN without sending to all sessions
	if !quiet {
		session.Stderr = newNameWriter(host, os.Stderr)
		session.Stdout = newNameWriter(host, os.Stdout)
	}
	for key, value := range c.Env {
		if err := session.Setenv(key, value); err != nil {
			return err
		}
	}
	return session.Run(c.Cmd)
}

// cleanHost parses out the hostname/ip and port.  If no port is
// specified then port 22 is appended to the hostname/ip
func cleanHost(host string) (string, error) {
	h, port, err := net.SplitHostPort(host)
	if err != nil {
		if !strings.Contains(err.Error(), "missing port in address") {
			return "", err
		}
		port = "22"
		h = host
	}
	if port == "" {
		port = "22"
	}
	return net.JoinHostPort(h, port), nil
}

func main() {
	app := cli.NewApp()
	app.Name = "slex"
	app.Usage = "SSH commands multiplexed"
	app.Version = "1"
	app.Author = "@crosbymichael"
	app.Email = "crosbymichael@gmail.com"
	app.Before = preload
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "enable debug output for the logs",
		},
		cli.StringSliceFlag{
			Name:  "host",
			Value: &cli.StringSlice{},
			Usage: "SSH host address",
		},
		cli.StringFlag{
			Name:  "hosts",
			Usage: "file containing host addresses separated by a new line",
		},
		cli.StringFlag{
			Name:  "user,u",
			Value: "root",
			Usage: "user to execute the command as",
		},
		cli.StringFlag{
			Name:  "identity,i",
			Value: "id_rsa",
			Usage: "SSH identity to use for connecting to the host",
		},
		cli.BoolFlag{
			Name:  "agent,A",
			Usage: "Forward authentication request to the ssh agent",
		},
		cli.StringSliceFlag{
			Name:  "env,e",
			Usage: "set environment variables for SSH command",
			Value: &cli.StringSlice{},
		},
		cli.BoolFlag{
			Name:  "quiet,q",
			Usage: "disable output from the ssh command",
		},
	}
	app.Action = multiplexAction
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

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

const (
	version         = "0.2"
	cacheExpiration = 12 * time.Hour
)

func main() {
	log.Printf("Kathisto v%s - Server-Side rendering with Go/PhantomJS\n", version)
	pubDir := os.Getenv("PUBLIC_DIR")
	if pubDir == "" {
		pubDir = "/dist"
	}

	// Create a PhantomJS renderer and attach the prerender func to /
	r := NewPJSRenderer(cacheExpiration, fmt.Sprintf("Kathisto/%s", version))
	rs := NewService(r, os.Getenv("STRICT_HOST"), pubDir)
	http.HandleFunc("/", rs.Prerender)

	// Spin up a TLS goroutine if a cert and key are found
	certFile, keyFile := os.Getenv("CERT_FILE"), os.Getenv("KEY_FILE")
	if certFile != "" && keyFile != "" {
		log.Println("Listening on port :443")
		go http.ListenAndServeTLS(":443", certFile, keyFile, nil)
	}

	port := os.Getenv("PORT")
	if port == "" {
		port = "80"
	}

	// Always run a basic http server
	log.Println("Listening on port :", port)
	http.ListenAndServe(":"+port, nil)
}
<commit_msg>Removing tls<commit_after>package main

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

const (
	version         = "0.2"
	cacheExpiration = 12 * time.Hour
)

func main() {
	log.Printf("Kathisto v%s - Server-Side rendering with Go/PhantomJS\n", version)
	pubDir := os.Getenv("PUBLIC_DIR")
	if pubDir == "" {
		pubDir = "/dist"
	}

	// Create a PhantomJS renderer and attach the prerender func to /
	r := NewPJSRenderer(cacheExpiration, fmt.Sprintf("Kathisto/%s", version))
	rs := NewService(r, os.Getenv("STRICT_HOST"), pubDir)
	http.HandleFunc("/", rs.Prerender)

	port := os.Getenv("PORT")
	if port == "" {
		port = "80"
	}

	// Always run a basic http server
	log.Println("Listening on port :", port)
	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/optiopay/klar/clair"
	"github.com/optiopay/klar/docker"
)

var store = make(map[string][]*clair.Vulnerability)

func main() {
	fail := func(format string, a ...interface{}) {
		fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", format), a...)
		os.Exit(2)
	}

	if len(os.Args) != 2 {
		fail("Image name must be provided")
	}

	conf, err := newConfig(os.Args)
	if err != nil {
		fail("Invalid options: %s", err)
	}

	if !conf.JSONOutput {
		fmt.Fprintf(os.Stderr, "clair timeout %s\n", conf.ClairTimeout)
		fmt.Fprintf(os.Stderr, "docker timeout: %s\n", conf.DockerConfig.Timeout)
	}
	whitelist := &vulnerabilitiesWhitelist{}
	if conf.WhiteListFile != "" {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "whitelist file: %s\n", conf.WhiteListFile)
		}
		whitelist, err = parseWhitelistFile(conf.WhiteListFile)
		if err != nil {
			fail("Could not parse whitelist file: %s", err)
		}
	} else {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "no whitelist file\n")
		}
	}

	image, err := docker.NewImage(&conf.DockerConfig)
	if err != nil {
		fail("Can't parse qname: %s", err)
	}

	err = image.Pull()
	if err != nil {
		fail("Can't pull image: %s", err)
	}

	output := jsonOutput{
		Vulnerabilities: make(map[string][]*clair.Vulnerability),
	}

	if len(image.FsLayers) == 0 {
		fail("Can't pull fsLayers")
	} else {
		if conf.JSONOutput {
			output.LayerCount = len(image.FsLayers)
		} else {
			fmt.Printf("Analysing %d layers\n", len(image.FsLayers))
		}
	}

	var vs []*clair.Vulnerability
	for _, ver := range []int{1, 3} {
		c := clair.NewClair(conf.ClairAddr, ver, conf.ClairTimeout)
		vs, err = c.Analyse(image)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to analyze using API v%d: %s\n", ver, err)
		} else {
			if !conf.JSONOutput {
				fmt.Printf("Got results from Clair API v%d\n", ver)
			}
			break
		}
	}
	if err != nil {
		fail("Failed to analyze, exiting")
	}

	//apply whitelist
	numVulnerabilites := len(vs)
	vs = filterWhitelist(whitelist, vs, image.Name)
	numVulnerabilitiesAfterWhitelist := len(vs)

	groupBySeverity(vs)
	vsNumber := 0

	if conf.JSONOutput {
		iteratePriorities(conf.ClairOutput, func(sev string) {
			if conf.IgnoreUnfixed {
				// need to iterate over store[sev]
				for _, v := range store[sev] {
					if v.FixedBy != "" {
						vsNumber++
					}
				}
			} else {
				vsNumber += len(store[sev])
			}
			output.Vulnerabilities[sev] = store[sev]
		})
		enc := json.NewEncoder(os.Stdout)
		enc.Encode(output)
	} else {
		if numVulnerabilitiesAfterWhitelist < numVulnerabilites {
			//display how many vulnerabilities were whitelisted
			fmt.Printf("Whitelisted %d vulnerabilities\n", numVulnerabilites-numVulnerabilitiesAfterWhitelist)
		}
		fmt.Printf("Found %d vulnerabilities\n", len(vs))
		iteratePriorities(priorities[0], func(sev string) { fmt.Printf("%s: %d\n", sev, len(store[sev])) })
		fmt.Printf("\n")

		iteratePriorities(conf.ClairOutput, func(sev string) {
			for _, v := range store[sev] {
				fmt.Printf("%s: [%s] \nFound in: %s [%s]\nFixed By: %s\n%s\n%s\n", v.Name, v.Severity, v.FeatureName,
v.FeatureVersion, v.FixedBy, v.Description, v.Link)
				fmt.Println("-----------------------------------------")
				if conf.IgnoreUnfixed {
					if v.FixedBy != "" {
						vsNumber++
					}
				} else {
					vsNumber++
				}
			}
		})

	}

	if vsNumber > conf.Threshold {
		os.Exit(1)
	}
}

func iteratePriorities(output string, f func(sev string)) {
	filtered := true
	for _, sev := range priorities {
		if filtered {
			if sev != output {
				continue
			} else {
				filtered = false
			}
		}

		if len(store[sev]) != 0 {
			f(sev)
		}
	}
}

func groupBySeverity(vs []*clair.Vulnerability) {
	for _, v := range vs {
		sevRow := vulnsBy(v.Severity, store)
		store[v.Severity] = append(sevRow, v)
	}
}

func vulnsBy(sev string, store map[string][]*clair.Vulnerability) []*clair.Vulnerability {
	items, found := store[sev]
	if !found {
		items = make([]*clair.Vulnerability, 0)
		store[sev] = items
	}
	return items
}

//Filter out whitelisted vulnerabilites
func filterWhitelist(whitelist *vulnerabilitiesWhitelist, vs []*clair.Vulnerability, imageName string) []*clair.Vulnerability {
	generalWhitelist := whitelist.General
	imageWhitelist := whitelist.Images

	filteredVs := make([]*clair.Vulnerability, 0, len(vs))

	for _, v := range vs {
		if _, exists := generalWhitelist[v.Name]; !exists {
			if _, exists := imageWhitelist[imageName][v.Name]; !exists {
				//vulnerability is not in the image whitelist, so add it to the list to return
				filteredVs = append(filteredVs, v)
			}
		}
	}

	return filteredVs
}

<commit_msg>Added table formatting to output<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/olekukonko/tablewriter"
	"github.com/optiopay/klar/clair"
	"github.com/optiopay/klar/docker"
)

const (
	ColorCritical = "\033[1;31m%s\033[0m"
	ColorHigh     = "\033[0;31m%s\033[0m"
	ColorMedium   = "\033[0;33m%s\033[0m"
	ColorLow      = "\033[0;94m%s\033[0m"
	ColorDefault  = "\033[0;97m%s\033[0m"
)

var store = make(map[string][]*clair.Vulnerability)

var Severity = map[string]int{
	"Defcon1":    7,
	"Critical":   6,
	"High":       5,
	"Medium":     4,
	"Low":        3,
	"Negligible": 2,
	"Unknown":    1,
}

func getSeverityStyle(status string) string {
	var colorStyle = ColorDefault
	if Severity[status] >= 6 {
		colorStyle = ColorCritical
	} else if Severity[status] >= 5 {
		colorStyle = ColorHigh
	} else if Severity[status] >= 4 {
		colorStyle = ColorMedium
	} else if Severity[status] >= 2 {
		colorStyle = ColorLow
	}

	return fmt.Sprintf(colorStyle, status)
}

func main() {
	fail := func(format string, a ...interface{}) {
		fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", format), a...)
		os.Exit(2)
	}

	if len(os.Args) != 2 {
		fail("Image name must be provided")
	}

	conf, err := newConfig(os.Args)
	if err != nil {
		fail("Invalid options: %s", err)
	}

	if !conf.JSONOutput {
		fmt.Fprintf(os.Stderr, "clair timeout %s\n", conf.ClairTimeout)
		fmt.Fprintf(os.Stderr, "docker timeout: %s\n", conf.DockerConfig.Timeout)
	}
	whitelist := &vulnerabilitiesWhitelist{}
	if conf.WhiteListFile != "" {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "whitelist file: %s\n", conf.WhiteListFile)
		}
		whitelist, err = parseWhitelistFile(conf.WhiteListFile)
		if err != nil {
			fail("Could not parse whitelist file: %s", err)
		}
	} else {
		if !conf.JSONOutput {
			fmt.Fprintf(os.Stderr, "no whitelist file\n")
		}
	}

	image, err := docker.NewImage(&conf.DockerConfig)
	if err != nil {
		fail("Can't parse qname: %s", err)
	}

	err = image.Pull()
	if err != nil {
		fail("Can't pull image: %s", err)
	}

	output := jsonOutput{
		Vulnerabilities: make(map[string][]*clair.Vulnerability),
	}

	if len(image.FsLayers) == 0 {
		fail("Can't pull fsLayers")
	} else {
		if conf.JSONOutput {
			output.LayerCount = len(image.FsLayers)
		} else {
			fmt.Printf("Analysing %d layers\n", len(image.FsLayers))
		}
	}

	var vs []*clair.Vulnerability
	for _, ver := range []int{1, 3} {
		c := clair.NewClair(conf.ClairAddr, ver, conf.ClairTimeout)
		vs, err = c.Analyse(image)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to analyze using API v%d: %s\n", ver, err)
		} else {
			if !conf.JSONOutput {
				fmt.Printf("Got results from Clair API v%d\n", ver)
			}
			break
		}
	}
	if err != nil {
		fail("Failed to analyze, exiting")
	}

	//apply whitelist
	numVulnerabilites := len(vs)
	vs = filterWhitelist(whitelist, vs, image.Name)
	numVulnerabilitiesAfterWhitelist := len(vs)

	groupBySeverity(vs)
	vsNumber := 0

	if conf.JSONOutput {
		iteratePriorities(conf.ClairOutput, func(sev string) {
			if conf.IgnoreUnfixed {
				// need to iterate over store[sev]
				for _, v := range store[sev] {
					if v.FixedBy != "" {
						vsNumber++
					}
				}
			} else {
				vsNumber += len(store[sev])
			}
			output.Vulnerabilities[sev] = store[sev]
		})
		enc := json.NewEncoder(os.Stdout)
		enc.Encode(output)
	} else {
		if numVulnerabilitiesAfterWhitelist < numVulnerabilites {
			//display how many vulnerabilities were whitelisted
			fmt.Printf("Whitelisted %d vulnerabilities\n", numVulnerabilites-numVulnerabilitiesAfterWhitelist)
		}
		fmt.Printf("Found %d vulnerabilities\n", len(vs))
		iteratePriorities(priorities[0], func(sev string) { fmt.Printf("%s: %d\n", sev, len(store[sev])) })
		fmt.Printf("\n")

		table := tablewriter.NewWriter(os.Stdout)
		header := []string{
			"Severity", "Name", "FeatureName", "FeatureVersion", "FixedBy", "Description", "Link",
		}
		table.SetHeader(header)
		table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
		table.SetRowSeparator("-")
		table.SetRowLine(true)
		table.SetAlignment(tablewriter.ALIGN_LEFT)

		var data [][]string

		iteratePriorities(conf.ClairOutput, func(sev string) {
			for _, v := range store[sev] {
				data = append(data, []string{
					getSeverityStyle(v.Severity),
					v.Name,
					v.FeatureName,
					v.FeatureVersion,
					v.FixedBy,
					v.Description,
					v.Link,
				})

				if conf.IgnoreUnfixed {
					if v.FixedBy != "" {
						vsNumber++
					}
				} else {
					vsNumber++
				}
			}
		})

		table.AppendBulk(data)

		if len(data) > 0 {
			table.Render()
		}

	}

	if vsNumber > conf.Threshold {
		os.Exit(1)
	}
}

func iteratePriorities(output string, f func(sev string)) {
	filtered := true
	for _, sev := range priorities {
		if filtered {
			if sev != output {
				continue
			} else {
				filtered = false
			}
		}

		if len(store[sev]) != 0 {
			f(sev)
		}
	}
}

func groupBySeverity(vs []*clair.Vulnerability) {
	for _, v := range vs {
		sevRow := vulnsBy(v.Severity, store)
		store[v.Severity] = append(sevRow, v)
	}
}

func vulnsBy(sev string, store map[string][]*clair.Vulnerability) []*clair.Vulnerability {
	items, found := store[sev]
	if !found {
		items = make([]*clair.Vulnerability, 0)
		store[sev] = items
	}
	return items
}

//Filter out whitelisted vulnerabilites
func filterWhitelist(whitelist *vulnerabilitiesWhitelist, vs []*clair.Vulnerability, imageName string) []*clair.Vulnerability {
	generalWhitelist := whitelist.General
	imageWhitelist := whitelist.Images

	filteredVs := make([]*clair.Vulnerability, 0, len(vs))

	for _, v := range vs {
		if _, exists := generalWhitelist[v.Name]; !exists {
			if _, exists := imageWhitelist[imageName][v.Name]; !exists {
				//vulnerability is not in the image whitelist, so add it to the list to return
				filteredVs = append(filteredVs, v)
			}
		}
	}

	return filteredVs
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"time"
)

const (
	waitTime  = 3 * time.Second
	execDigit = 5
)

func main() {
	c := new(http.Client)
	c.CheckRedirect = func(req *http.Request, via []*http.Request) error { return errors.New("not redirect") }

	runes := []rune{'0'}

	for {
		var uri string
		for _, v := range runes {
			uri += string(v)
		}

		resp, err := c.Get("https://git.io/" + uri)
		if err == nil {
			resp.Body.Close()
		}

		if resp.StatusCode == 404 {
			fmt.Println(uri + " OK!")
		} else {
			fmt.Fprintln(os.Stderr, uri+" NG")
			fmt.Fprintln(os.Stderr, "Location:", resp.Header.Get("Location"))
		}

		if runes[len(runes)-1] == 'Z' {
			// carry over
			addFlg := true
			for i := len(runes) - 1; i > -1; i-- {
				beforeRune := runes[i]
				runes[i] = getNextRune(runes[i])
				if beforeRune != 'Z' {
					addFlg = false
					break
				}
			}

			if addFlg {
				runes = append(runes, '0')
			}
		} else {
			runes[len(runes)-1] = getNextRune(runes[len(runes)-1])
		}

		if len(runes) > execDigit {
			// exit
			break
		}

		time.Sleep(waitTime)
	}
}

func getNextRune(r rune) rune {
	// 0 -> 9, a -> z, A -> Z
	if r == '9' {
		return 'a'
	} else if r == 'z' {
		return 'A'
	} else if r == 'Z' {
		return '0'
	}

	r++
	return r
}
<commit_msg>replace print format<commit_after>package main

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"time"
)

const (
	waitTime  = 3 * time.Second
	execDigit = 5
	baseURL   = "https://git.io/"
	okFmt     = "%s OK!\n"
	ngFmt     = "%s NG!\n"
	locFmt    = "Location: %s\n"
)

func main() {
	c := new(http.Client)
	c.CheckRedirect = func(req *http.Request, via []*http.Request) error { return errors.New("not redirect") }

	runes := []rune{'0'}

	for {
		var uri string
		for _, v := range runes {
			uri += string(v)
		}

		resp, err := c.Get(baseURL + uri)
		if err == nil {
			resp.Body.Close()
		}

		if resp.StatusCode == 404 {
			fmt.Printf(okFmt, uri)
		} else {
			fmt.Fprintf(os.Stderr, ngFmt, uri)
			fmt.Fprintf(os.Stderr, locFmt, resp.Header.Get("Location"))
		}

		if runes[len(runes)-1] == 'Z' {
			// carry over
			addFlg := true
			for i := len(runes) - 1; i > -1; i-- {
				beforeRune := runes[i]
				runes[i] = getNextRune(runes[i])
				if beforeRune != 'Z' {
					addFlg = false
					break
				}
			}

			if addFlg {
				runes = append(runes, '0')
			}
		} else {
			runes[len(runes)-1] = getNextRune(runes[len(runes)-1])
		}

		if len(runes) > execDigit {
			// exit
			break
		}

		time.Sleep(waitTime)
	}
}

func getNextRune(r rune) rune {
	// 0 -> 9, a -> z, A -> Z
	if r == '9' {
		return 'a'
	} else if r == 'z' {
		return 'A'
	} else if r == 'Z' {
		return '0'
	}

	r++
	return r
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"
)

const version = "1.0.3"

func open(path string) (*bufio.Writer, *os.File, int64) {
	if fileInfo, err := os.Stat(path); err == nil {
		f, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0666)
		Check(err, "Failed to open log file for appending")
		return bufio.NewWriter(f), f, fileInfo.Size()
	} else if os.IsNotExist(err) {
		f, err := os.Create(path)
		Check(err, "Failed to create output log file")
		return bufio.NewWriter(f), f, 0
	} else {
		panic(err)
	}
}

func close(w *bufio.Writer, f *os.File) {
	Check(w.Flush(), "Failed to flush output writer")
	Check(f.Close(), "Failed to close output log file")
}

type oldestFirst []string

func timestampSuffix(s string) int64 {
	pieces := strings.Split(s, ".")
	Assert(len(pieces) < 2, fmt.Sprintf("Missing timestamp suffix: %s", s))
	t, err := strconv.ParseInt(pieces[len(pieces)-1], 10, 64)
	Check(err, fmt.Sprintf("Failed to parse timestamp suffix from: %s", s))
	return t
}

func (s oldestFirst) Len() int      { return len(s) }
func (s oldestFirst) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s oldestFirst) Less(i, j int) bool {
	return timestampSuffix(s[i]) < timestampSuffix(s[j])
}

func rotate(w *bufio.Writer, f *os.File, path string, maxOldFiles int) (
	*bufio.Writer, *os.File, int64) {
	close(w, f)

	now := time.Now()
	rotatedPath := fmt.Sprintf("%s.%d", path, now.UnixNano())
	os.Rename(path, rotatedPath)

	// Clean up old rotated files.
	globPattern := path + ".*"
	rotatedFiles, err := filepath.Glob(globPattern)
	Check(err, "Failed to look for old/rotated log files")
	sort.Sort(oldestFirst(rotatedFiles))
	if len(rotatedFiles) > maxOldFiles {
		for _, staleFile := range rotatedFiles[:len(rotatedFiles)-maxOldFiles] {
			os.Remove(staleFile)
		}
	}

	// Open a new file to write to.
	return open(path)
}

type VError struct {
	message string
	child   error
}

func (e VError) Error() string {
	return fmt.Sprintf("%s: %s", e.message, e.child.Error())
}

func NewVError(message string, child error) VError {
	return VError{message, child}
}

func Check(err error, message string) {
	if err != nil {
		panic(NewVError(message, err))
	}
}

func Assert(condition bool, message string) {
	if !condition {
		panic(errors.New(message))
	}
}

func main() {
	logPtr := flag.String("log", "",
		"Write logs to this path. Rotated files will have a timestamp suffix.")
	maxOldFilesPtr := flag.Int("max-old-files", 2,
		"Keep this many of the most recent rotated files and delete the others.")
	maxBytesPtr := flag.Int64("max-bytes", 50*(1<<20),
		"Rotate log files at this size.")
	versionPtr := flag.Bool("version", false, "Print version.")
	flag.Parse()
	if *versionPtr {
		fmt.Println("github.com/jtconnor/logwheel version " + version)
		return
	}
	Assert(*logPtr == "", "Requires --log")

	scanner := bufio.NewScanner(os.Stdin)
	w, f, bytesWritten := open(*logPtr)
	for scanner.Scan() {
		line := scanner.Text()
		Check(scanner.Err(), "Failed to scan input")

		lineLen := int64(len(line))

		if lineLen > *maxBytesPtr-1 {
			line = line[:*maxBytesPtr-1]
		}

		if bytesWritten+lineLen+1 > *maxBytesPtr {
			w, f, bytesWritten = rotate(w, f, *logPtr, *maxOldFilesPtr)
		}

		w.WriteString(line)
		w.WriteString("\n")
		bytesWritten += lineLen + 1
	}
	close(w, f)
}
<commit_msg>fixit! Reverse Assert conditionals.<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"time"
)

const version = "1.0.4"

func open(path string) (*bufio.Writer, *os.File, int64) {
	if fileInfo, err := os.Stat(path); err == nil {
		f, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0666)
		Check(err, "Failed to open log file for appending")
		return bufio.NewWriter(f), f, fileInfo.Size()
	} else if os.IsNotExist(err) {
		f, err := os.Create(path)
		Check(err, "Failed to create output log file")
		return bufio.NewWriter(f), f, 0
	} else {
		panic(err)
	}
}

func close(w *bufio.Writer, f *os.File) {
	Check(w.Flush(), "Failed to flush output writer")
	Check(f.Close(), "Failed to close output log file")
}

type oldestFirst []string

func timestampSuffix(s string) int64 {
	pieces := strings.Split(s, ".")
	Assert(len(pieces) >= 2, fmt.Sprintf("Missing timestamp suffix: %s", s))
	t, err := strconv.ParseInt(pieces[len(pieces)-1], 10, 64)
	Check(err, fmt.Sprintf("Failed to parse timestamp suffix from: %s", s))
	return t
}

func (s oldestFirst) Len() int      { return len(s) }
func (s oldestFirst) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s oldestFirst) Less(i, j int) bool {
	return timestampSuffix(s[i]) < timestampSuffix(s[j])
}

func rotate(w *bufio.Writer, f *os.File, path string, maxOldFiles int) (
	*bufio.Writer, *os.File, int64) {
	close(w, f)

	now := time.Now()
	rotatedPath := fmt.Sprintf("%s.%d", path, now.UnixNano())
	os.Rename(path, rotatedPath)

	// Clean up old rotated files.
	globPattern := path + ".*"
	rotatedFiles, err := filepath.Glob(globPattern)
	Check(err, "Failed to look for old/rotated log files")
	sort.Sort(oldestFirst(rotatedFiles))
	if len(rotatedFiles) > maxOldFiles {
		for _, staleFile := range rotatedFiles[:len(rotatedFiles)-maxOldFiles] {
			os.Remove(staleFile)
		}
	}

	// Open a new file to write to.
	return open(path)
}

type VError struct {
	message string
	child   error
}

func (e VError) Error() string {
	return fmt.Sprintf("%s: %s", e.message, e.child.Error())
}

func NewVError(message string, child error) VError {
	return VError{message, child}
}

func Check(err error, message string) {
	if err != nil {
		panic(NewVError(message, err))
	}
}

func Assert(condition bool, message string) {
	if !condition {
		panic(errors.New(message))
	}
}

func main() {
	logPtr := flag.String("log", "",
		"Write logs to this path. Rotated files will have a timestamp suffix.")
	maxOldFilesPtr := flag.Int("max-old-files", 2,
		"Keep this many of the most recent rotated files and delete the others.")
	maxBytesPtr := flag.Int64("max-bytes", 50*(1<<20),
		"Rotate log files at this size.")
	versionPtr := flag.Bool("version", false, "Print version.")
	flag.Parse()
	if *versionPtr {
		fmt.Println("github.com/jtconnor/logwheel version " + version)
		return
	}
	Assert(*logPtr != "", "Requires --log")

	scanner := bufio.NewScanner(os.Stdin)
	w, f, bytesWritten := open(*logPtr)
	for scanner.Scan() {
		line := scanner.Text()
		Check(scanner.Err(), "Failed to scan input")

		lineLen := int64(len(line))

		if lineLen > *maxBytesPtr-1 {
			line = line[:*maxBytesPtr-1]
		}

		if bytesWritten+lineLen+1 > *maxBytesPtr {
			w, f, bytesWritten = rotate(w, f, *logPtr, *maxOldFilesPtr)
		}

		w.WriteString(line)
		w.WriteString("\n")
		bytesWritten += lineLen + 1
	}
	close(w, f)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	// "syscall"
	// "runtime/pprof"
)

var sigChan = make(chan os.Signal, 1)

// var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func sigHandler() {
	for sig := range sigChan {
		info.Printf("%v caught, exit\n", sig)
		writeDomainSet()
		break
	}
	os.Exit(0)
}

func main() {
	// Parse flags after load config to allow override options in config
	loadConfig()
	flag.Parse()
	initProxyServerAddr()

	if config.socksAddr == "" {
		fmt.Println("Socks server address required")
		os.Exit(1)
	}

	setSelfURL()

	if config.printVer {
		printVersion()
		os.Exit(0)
	}

	initLog()
	loadDomainSet()
	/*
		if *cpuprofile != "" {
			f, err := os.Create(*cpuprofile)
			if err != nil {
				info.Println(err)
				os.Exit(1)
			}
			pprof.StartCPUProfile(f)
			signal.Notify(c, os.Interrupt)
			go func() {
				for sig := range c {
					info.Printf("captured %v, stopping profiler and exiting..", sig)
					pprof.StopCPUProfile()
					os.Exit(0)
				}
			}()
		}
	*/

	runtime.GOMAXPROCS(config.numProc)

	signal.Notify(sigChan, syscall.SIGINT)
	signal.Notify(sigChan, syscall.SIGTERM)
	go sigHandler()

	go runSSH()

	py := NewProxy(config.listenAddr)
	py.Serve()
}
<commit_msg>Log message if no socks server specified.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	// "syscall"
	// "runtime/pprof"
)

var sigChan = make(chan os.Signal, 1)

// var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func sigHandler() {
	for sig := range sigChan {
		info.Printf("%v caught, exit\n", sig)
		writeDomainSet()
		break
	}
	os.Exit(0)
}

func main() {
	// Parse flags after load config to allow override options in config
	loadConfig()
	flag.Parse()
	initProxyServerAddr()

	if config.socksAddr == "" {
		info.Println("no socks server address, can't handle blocked sites")
	}

	setSelfURL()

	if config.printVer {
		printVersion()
		os.Exit(0)
	}

	initLog()
	loadDomainSet()
	/*
		if *cpuprofile != "" {
			f, err := os.Create(*cpuprofile)
			if err != nil {
				info.Println(err)
				os.Exit(1)
			}
			pprof.StartCPUProfile(f)
			signal.Notify(c, os.Interrupt)
			go func() {
				for sig := range c {
					info.Printf("captured %v, stopping profiler and exiting..", sig)
					pprof.StopCPUProfile()
					os.Exit(0)
				}
			}()
		}
	*/

	runtime.GOMAXPROCS(config.numProc)

	signal.Notify(sigChan, syscall.SIGINT)
	signal.Notify(sigChan, syscall.SIGTERM)
	go sigHandler()

	go runSSH()

	py := NewProxy(config.listenAddr)
	py.Serve()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/joho/godotenv"
	"github.com/urfave/cli"
)

var build = "0" // build number set at compile-time

func main() {
	app := cli.NewApp()
	app.Name = "github-release plugin"
	app.Usage = "github-release plugin"
	app.Action = run
	app.Version = fmt.Sprintf("1.0.%s", build)
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "api-key",
			Usage:  "api key to access github api",
			EnvVar: "PLUGIN_API_KEY,GITHUB_RELEASE_API_KEY",
		},
		cli.StringSliceFlag{
			Name:   "files",
			Usage:  "list of files to upload",
			EnvVar: "PLUGIN_FILES,GITHUB_RELEASE_FILES",
		},
		cli.StringFlag{
			Name:   "file-exists",
			Value:  "overwrite",
			Usage:  "what to do if file already exist",
			EnvVar: "PLUGIN_FILE_EXISTS,GITHUB_RELEASE_FILE_EXISTS",
		},
		cli.StringSliceFlag{
			Name:   "checksum",
			Usage:  "generate specific checksums",
			EnvVar: "PLUGIN_CHECKSUM,GITHUB_RELEASE_CHECKSUM",
		},
		cli.BoolFlag{
			Name:   "draft",
			Usage:  "create a draft release",
			EnvVar: "PLUGIN_DRAFT,GITHUB_RELEASE_DRAFT",
		},
		cli.StringFlag{
			Name:   "base-url",
			Value:  "https://api.github.com/",
			Usage:  "api url, needs to be changed for ghe",
			EnvVar: "PLUGIN_BASE_URL,GITHUB_RELEASE_BASE_URL",
		},
		cli.StringFlag{
			Name:   "upload-url",
			Value:  "https://uploads.github.com/",
			Usage:  "upload url, needs to be changed for ghe",
			EnvVar: "PLUGIN_UPLOAD_URL,GITHUB_RELEASE_UPLOAD_URL",
		},

		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:   "build.event",
			Value:  "push",
			Usage:  "build event",
			EnvVar: "DRONE_BUILD_EVENT",
		},
		cli.StringFlag{
			Name:   "commit.ref",
			Value:  "refs/heads/master",
			Usage:  "git commit ref",
			EnvVar: "DRONE_COMMIT_REF",
		},
		cli.StringFlag{
			Name:  "env-file",
			Usage: "source env file",
		},
	}

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

func run(c *cli.Context) error {
	if c.String("env-file") != "" {
		_ = godotenv.Load(c.String("env-file"))
	}

	plugin := Plugin{
		Repo: Repo{
			Owner: c.String("repo.owner"),
			Name:  c.String("repo.name"),
		},
		Build: Build{
			Event: c.String("build.event"),
		},
		Commit: Commit{
			Ref: c.String("commit.ref"),
		},
		Config: Config{
			APIKey:     c.String("api-key"),
			Files:      c.StringSlice("files"),
			FileExists: c.String("file-exists"),
			Checksum:   c.StringSlice("checksum"),
			Draft:      c.Bool("draft"),
			BaseURL:    c.String("base-url"),
			UploadURL:  c.String("upload-url"),
		},
	}

	return plugin.Exec()
}
<commit_msg>Ability to use GITHUB_TOKEN as secret<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/joho/godotenv"
	"github.com/urfave/cli"
)

var build = "0" // build number set at compile-time

func main() {
	app := cli.NewApp()
	app.Name = "github-release plugin"
	app.Usage = "github-release plugin"
	app.Action = run
	app.Version = fmt.Sprintf("1.0.%s", build)
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "api-key",
			Usage:  "api key to access github api",
			EnvVar: "PLUGIN_API_KEY,GITHUB_RELEASE_API_KEY,GITHUB_TOKEN",
		},
		cli.StringSliceFlag{
			Name:   "files",
			Usage:  "list of files to upload",
			EnvVar: "PLUGIN_FILES,GITHUB_RELEASE_FILES",
		},
		cli.StringFlag{
			Name:   "file-exists",
			Value:  "overwrite",
			Usage:  "what to do if file already exist",
			EnvVar: "PLUGIN_FILE_EXISTS,GITHUB_RELEASE_FILE_EXISTS",
		},
		cli.StringSliceFlag{
			Name:   "checksum",
			Usage:  "generate specific checksums",
			EnvVar: "PLUGIN_CHECKSUM,GITHUB_RELEASE_CHECKSUM",
		},
		cli.BoolFlag{
			Name:   "draft",
			Usage:  "create a draft release",
			EnvVar: "PLUGIN_DRAFT,GITHUB_RELEASE_DRAFT",
		},
		cli.StringFlag{
			Name:   "base-url",
			Value:  "https://api.github.com/",
			Usage:  "api url, needs to be changed for ghe",
			EnvVar: "PLUGIN_BASE_URL,GITHUB_RELEASE_BASE_URL",
		},
		cli.StringFlag{
			Name:   "upload-url",
			Value:  "https://uploads.github.com/",
			Usage:  "upload url, needs to be changed for ghe",
			EnvVar: "PLUGIN_UPLOAD_URL,GITHUB_RELEASE_UPLOAD_URL",
		},

		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:   "build.event",
			Value:  "push",
			Usage:  "build event",
			EnvVar: "DRONE_BUILD_EVENT",
		},
		cli.StringFlag{
			Name:   "commit.ref",
			Value:  "refs/heads/master",
			Usage:  "git commit ref",
			EnvVar: "DRONE_COMMIT_REF",
		},
		cli.StringFlag{
			Name:  "env-file",
			Usage: "source env file",
		},
	}

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

func run(c *cli.Context) error {
	if c.String("env-file") != "" {
		_ = godotenv.Load(c.String("env-file"))
	}

	plugin := Plugin{
		Repo: Repo{
			Owner: c.String("repo.owner"),
			Name:  c.String("repo.name"),
		},
		Build: Build{
			Event: c.String("build.event"),
		},
		Commit: Commit{
			Ref: c.String("commit.ref"),
		},
		Config: Config{
			APIKey:     c.String("api-key"),
			Files:      c.StringSlice("files"),
			FileExists: c.String("file-exists"),
			Checksum:   c.StringSlice("checksum"),
			Draft:      c.Bool("draft"),
			BaseURL:    c.String("base-url"),
			UploadURL:  c.String("upload-url"),
		},
	}

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


<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/bmizerany/pat"
	"github.com/mozillazg/comic/views"
)

func BasicAuth(
	f func(http.ResponseWriter, *http.Request), user, pass []byte,
) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		const basicAuthPrefix string = "Basic "

		// Get the Basic Authentication credentials
		auth := r.Header.Get("Authorization")
		if strings.HasPrefix(auth, basicAuthPrefix) {
			// Check credentials
			payload, err := base64.StdEncoding.DecodeString(
				auth[len(basicAuthPrefix):],
			)
			if err == nil {
				pair := bytes.SplitN(payload, []byte(":"), 2)
				if len(pair) == 2 && bytes.Equal(pair[0], user) &&
					bytes.Equal(pair[1], pass) {
					// Delegate request to the given handle
					f(w, r)
					return
				}
			}
		}

		// Request Basic Authentication otherwise
		w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
		http.Error(w, http.StatusText(http.StatusUnauthorized),
			http.StatusUnauthorized)
	}
}

func main() {
	listen := os.Getenv("COMIC_LISTEN")
	user := []byte(os.Getenv("COMIC_USER"))
	pass := []byte(os.Getenv("COMIC_PASSWD"))

	router := pat.New()
	router.Get("/", http.HandlerFunc(views.LastComicView))
	router.Get("/first", http.HandlerFunc(views.FirstComicView))
	router.Get("/last", http.HandlerFunc(views.LastComicView))
	router.Get("/random", http.HandlerFunc(views.RandomComicView))
	router.Get("/admin", http.HandlerFunc(BasicAuth(views.ListView, user, pass)))

	router.Post("/api/comics", http.HandlerFunc(BasicAuth(views.CreateAPIView, user, pass)))
	router.Get("/api/comics", http.HandlerFunc(BasicAuth(views.ListAPIView, user, pass)))
	router.Get("/api/comics/:id", http.HandlerFunc(BasicAuth(views.GetAPIView, user, pass)))
	router.Del("/api/comics/:id", http.HandlerFunc(BasicAuth(views.DeleteAPIView, user, pass)))
	router.Put("/api/comics/:id", http.HandlerFunc(BasicAuth(views.UpdateAPIView, user, pass)))

	router.Get("/archive", http.HandlerFunc(views.ArchiveView))
	router.Get("/:id", http.HandlerFunc(views.GetComicView))

	http.Handle("/", router)
	log.Printf("listen %s\n", listen)
	err := http.ListenAndServe(listen, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>improve BasicAuth<commit_after>package main

import (
	"bytes"
	"encoding/base64"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/bmizerany/pat"
	"github.com/mozillazg/comic/views"
)

type ViewFunc func(http.ResponseWriter, *http.Request)

func BasicAuth(f ViewFunc, user, passwd []byte) ViewFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		basicAuthPrefix := "Basic "

		// 获取 request header
		auth := r.Header.Get("Authorization")
		// 如果是 http basic auth
		if strings.HasPrefix(auth, basicAuthPrefix) {
			// 解码认证信息
			payload, err := base64.StdEncoding.DecodeString(
				auth[len(basicAuthPrefix):],
			)
			if err == nil {
				pair := bytes.SplitN(payload, []byte(":"), 2)
				if len(pair) == 2 && bytes.Equal(pair[0], user) &&
					bytes.Equal(pair[1], passwd) {
					// 执行被装饰的函数
					f(w, r)
					return
				}
			}
		}

		// 认证失败，提示 401 Unauthorized
		// Restricted 可以改成其他的值，作用类似于 session ,这样就不会每次访问页面都提示登录
		w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
		// 401 状态码
		w.WriteHeader(http.StatusUnauthorized)
	}
}

func main() {
	listen := os.Getenv("COMIC_LISTEN")
	user := []byte(os.Getenv("COMIC_USER"))
	pass := []byte(os.Getenv("COMIC_PASSWD"))

	router := pat.New()
	router.Get("/", http.HandlerFunc(views.LastComicView))
	router.Get("/first", http.HandlerFunc(views.FirstComicView))
	router.Get("/last", http.HandlerFunc(views.LastComicView))
	router.Get("/random", http.HandlerFunc(views.RandomComicView))
	router.Get("/admin", http.HandlerFunc(BasicAuth(views.ListView, user, pass)))

	router.Post("/api/comics", http.HandlerFunc(BasicAuth(views.CreateAPIView, user, pass)))
	router.Get("/api/comics", http.HandlerFunc(BasicAuth(views.ListAPIView, user, pass)))
	router.Get("/api/comics/:id", http.HandlerFunc(BasicAuth(views.GetAPIView, user, pass)))
	router.Del("/api/comics/:id", http.HandlerFunc(BasicAuth(views.DeleteAPIView, user, pass)))
	router.Put("/api/comics/:id", http.HandlerFunc(BasicAuth(views.UpdateAPIView, user, pass)))

	router.Get("/archive", http.HandlerFunc(views.ArchiveView))
	router.Get("/:id", http.HandlerFunc(views.GetComicView))

	http.Handle("/", router)
	log.Printf("listen %s\n", listen)
	err := http.ListenAndServe(listen, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

import "github.com/howeyc/fsnotify"
import "log"
import "flag"
import "fmt"
import "os"
import "os/exec"
import "regexp"

var versionStr = "0.1.0"

var goCommandSet = map[string][]string{
	"test":    []string{"go", "test"},
	"install": []string{"go", "install"},
	"build":   []string{"go", "build"},
	"fmt":     []string{"go", "fmt"},
	"run":     []string{"go", "run"},
}

func main() {
	var helpFlag = flag.Bool("h", false, "Show Help")
	var buildFlag = flag.Bool("b", true, "Run `go build`, the default behavior")
	var testFlag = flag.Bool("t", false, "Run `go test`")
	var installFlag = flag.Bool("i", false, "Run `go install`")
	var fmtFlag = flag.Bool("f", false, "Run `go fmt`")
	var runFlag = flag.Bool("r", false, "Run `go run`")
	var versionFlag = flag.Bool("v", false, "Version")

	var xFlag = flag.Bool("x", false, "Show verbose command")

	var useGrowl = flag.Bool("growl", false, "Use Growler")
	var gntpServer = flag.String("gntp", "", "The GNTP DSN")
	if *useGrowl && *gntpServer == "" {
		*gntpServer = "127.0.0.1:23053"
	}

	flag.Parse()
	args := flag.Args()

	if *helpFlag {
		fmt.Println("Usage: gomon [options] [dir] [-- command]")
		fmt.Println("   -b build")
		fmt.Println("   -t test")
		fmt.Println("   -i install")
		fmt.Println("   -x show verbose command")
		fmt.Println("   -h help")
		os.Exit(0)
	}
	if *versionFlag {
		fmt.Printf("gomon %s\n", versionStr)
		os.Exit(0)
	}

	var dirs = []string{}
	var cmds = []string{}

	var takeDir = true
	for _, a := range args {
		var exists, _ = FileExists(a)
		if a == "--" || (takeDir && !exists) {
			takeDir = false
			continue
		}
		if takeDir {
			dirs = append(dirs, a)
		} else {
			cmds = append(cmds, a)
		}
	}

	if len(cmds) == 0 {
		if *testFlag {
			cmds = goCommandSet["test"]
		} else if *buildFlag {
			cmds = goCommandSet["build"]
		} else if *installFlag {
			cmds = goCommandSet["install"]
		} else if *fmtFlag {
			cmds = goCommandSet["fmt"]
		} else if *runFlag {
			cmds = goCommandSet["run"]
		}
		if *xFlag && len(cmds) > 0 {
			cmds = append(cmds, "-x")
		}
	}

	if len(cmds) == 0 {
		fmt.Println("No command specified")
		os.Exit(2)
	}

	if len(dirs) == 0 {
		var cwd, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		dirs = []string{cwd}
	}

	fmt.Println("Watching", dirs, "for", cmds)

	watcher, err := fsnotify.NewWatcher()

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

	for _, dir := range dirs {
		subfolders := Subfolders(dir)
		for _, f := range subfolders {
			err = watcher.WatchFlags(f, fsnotify.FSN_CREATE|fsnotify.FSN_MODIFY)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	var wasFailed bool = false
	var cmd *exec.Cmd

	runCommand := func(cmd *exec.Cmd) {
		var err error
		err = cmd.Start()
		if err != nil {
			log.Println(err)
			if *useGrowl {
				notifyFail(gntpServer, err.Error(), "")
			}
			wasFailed = true
			return
		}
		err = cmd.Wait()
		if err != nil {
			log.Println(err)
			if *useGrowl {
				notifyFail(gntpServer, err.Error(), "")
			}
			wasFailed = true
			return
		}

		// fixed
		if wasFailed {
			wasFailed = false
			if *useGrowl {
				notifyFixed(gntpServer, "Fixed", "")
			}
			fmt.Println("Congratulations! It's fixed!")
		}
	}

	for {
		select {
		case e := <-watcher.Event:
			matched, err := regexp.MatchString("\\.(go|c|h)$", e.Name)
			if err != nil {
				log.Println(err)
			}

			if !matched {
				continue
			}

			log.Println("Event:", e)

			if cmd != nil && cmd.ProcessState != nil && !cmd.ProcessState.Exited() {
				err := cmd.Process.Kill()
				if err != nil {
					log.Println(err)
				}
			}
			cmd = exec.Command(cmds[0], cmds[1:]...)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			go runCommand(cmd)

		case err := <-watcher.Error:
			log.Println("Error:", err)
		}
	}

	watcher.Close()
}
<commit_msg>Fix flag options<commit_after>package main

import "github.com/howeyc/fsnotify"
import "log"
import "flag"
import "fmt"
import "os"
import "os/exec"
import "regexp"

var versionStr = "0.1.0"

var goCommandSet = map[string][]string{
	"test":    []string{"go", "test"},
	"install": []string{"go", "install"},
	"build":   []string{"go", "build"},
	"fmt":     []string{"go", "fmt"},
	"run":     []string{"go", "run"},
}

func main() {
	var helpFlag = flag.Bool("h", false, "Show Help")
	var buildFlag = flag.Bool("b", false, "Run `go build`, the default behavior")
	var testFlag = flag.Bool("t", false, "Run `go test`")
	var installFlag = flag.Bool("i", false, "Run `go install`")
	var fmtFlag = flag.Bool("f", false, "Run `go fmt`")
	var runFlag = flag.Bool("r", false, "Run `go run`")
	var versionFlag = flag.Bool("v", false, "Version")

	var xFlag = flag.Bool("x", false, "Show verbose command")

	var useGrowl = flag.Bool("growl", false, "Use Growler")
	var gntpServer = flag.String("gntp", "", "The GNTP DSN")
	if *useGrowl && *gntpServer == "" {
		*gntpServer = "127.0.0.1:23053"
	}

	flag.Parse()
	args := flag.Args()

	if *helpFlag {
		fmt.Println("Usage: gomon [options] [dir] [-- command]")
		fmt.Println("   -b build")
		fmt.Println("   -t test")
		fmt.Println("   -i install")
		fmt.Println("   -x show verbose command")
		fmt.Println("   -h help")
		os.Exit(0)
	}
	if *versionFlag {
		fmt.Printf("gomon %s\n", versionStr)
		os.Exit(0)
	}

	var dirs = []string{}
	var cmds = []string{}

	var takeDir = true
	for _, a := range args {
		var exists, _ = FileExists(a)
		if a == "--" || (takeDir && !exists) {
			takeDir = false
			continue
		}
		if takeDir {
			dirs = append(dirs, a)
		} else {
			cmds = append(cmds, a)
		}
	}

	if len(cmds) == 0 {
		if *testFlag {
			cmds = goCommandSet["test"]
		} else if *buildFlag {
			cmds = goCommandSet["build"]
		} else if *installFlag {
			cmds = goCommandSet["install"]
		} else if *fmtFlag {
			cmds = goCommandSet["fmt"]
		} else if *runFlag {
			cmds = goCommandSet["run"]
		} else {
			// default behavior
			cmds = goCommandSet["build"]
		}
		if *xFlag && len(cmds) > 0 {
			cmds = append(cmds, "-x")
		}
	}

	if len(cmds) == 0 {
		fmt.Println("No command specified")
		os.Exit(2)
	}

	if len(dirs) == 0 {
		var cwd, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		dirs = []string{cwd}
	}

	fmt.Println("Watching", dirs, "for", cmds)

	watcher, err := fsnotify.NewWatcher()

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

	for _, dir := range dirs {
		subfolders := Subfolders(dir)
		for _, f := range subfolders {
			err = watcher.WatchFlags(f, fsnotify.FSN_CREATE|fsnotify.FSN_MODIFY)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	var wasFailed bool = false
	var cmd *exec.Cmd

	runCommand := func(cmd *exec.Cmd) {
		var err error
		err = cmd.Start()
		if err != nil {
			log.Println(err)
			if *useGrowl {
				notifyFail(gntpServer, err.Error(), "")
			}
			wasFailed = true
			return
		}
		err = cmd.Wait()
		if err != nil {
			log.Println(err)
			if *useGrowl {
				notifyFail(gntpServer, err.Error(), "")
			}
			wasFailed = true
			return
		}

		// fixed
		if wasFailed {
			wasFailed = false
			if *useGrowl {
				notifyFixed(gntpServer, "Fixed", "")
			}
			fmt.Println("Congratulations! It's fixed!")
		}
	}

	for {
		select {
		case e := <-watcher.Event:
			matched, err := regexp.MatchString("\\.(go|c|h)$", e.Name)
			if err != nil {
				log.Println(err)
			}

			if !matched {
				continue
			}

			log.Println("Event:", e)

			if cmd != nil && cmd.ProcessState != nil && !cmd.ProcessState.Exited() {
				err := cmd.Process.Kill()
				if err != nil {
					log.Println(err)
				}
			}
			cmd = exec.Command(cmds[0], cmds[1:]...)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			go runCommand(cmd)

		case err := <-watcher.Error:
			log.Println("Error:", err)
		}
	}

	watcher.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"
)

const (
	tokenConfig = "INCOMING_SLACK_TOKEN"
	// Incoming payload form will have the following keys:
	// (See: https://api.slack.com/slash-commands)
	keyToken       = "token"
	keyTeamID      = "team_id"
	keyChannelId   = "channel_id"
	keyChannelName = "channel_name"
	keyUserID      = "user_id"
	keyUserName    = "user_name"
	keyCommand     = "command"
	keyText        = "text"
)

var (
	port int
	// Random animals cribbed from Google Drive's "Anonymous [Animal]" notifications
	animals = []string{
		"alligator", "anteater", "armadillo", "auroch", "axolotl", "badger", "bat", "beaver", "buffalo",
		"camel", "chameleon", "cheetah", "chipmunk", "chinchilla", "chupacabra", "cormorant", "coyote",
		"crow", "dingo", "dinosaur", "dolphin", "duck", "elephant", "ferret", "fox", "frog", "giraffe",
		"gopher", "grizzly", "hedgehog", "hippo", "hyena", "jackal", "ibex", "ifrit", "iguana", "koala",
		"kraken", "lemur", "leopard", "liger", "llama", "manatee", "mink", "monkey", "narwhal", "nyan cat",
		"orangutan", "otter", "panda", "penguin", "platypus", "python", "pumpkin", "quagga", "rabbit", "raccoon",
		"rhino", "sheep", "shrew", "skunk", "slow loris", "squirrel", "turtle", "walrus", "wolf", "wolverine", "wombat",
	}
)

// readAnonymousMessage parses the username and re-routes
// the message to the user from an anonymous animal
func readAnonymousMessage(r *http.Request) string {
	err := r.ParseForm()
	// TODO: Change HTTP status code
	if err != nil {
		return string(err.Error())
	}
	// Incoming POST's token should match the one set in Heroku
	if len(r.Form[keyToken]) == 0 || r.Form[keyToken][0] != os.Getenv(tokenConfig) {
		return "Tokens didn't match."
	}
	// Just return the message to see if it worked
	return r.Form[keyText][0]
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		result := readAnonymousMessage(r)
		fmt.Fprintf(w, result)
	})
	http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

func init() {
	flag.IntVar(&port, "port", 5000, "HTTP server port")
	flag.Parse()
}
<commit_msg>parse username, etc.<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strings"
)

const (
	tokenConfig = "INCOMING_SLACK_TOKEN"
	// Incoming payload form will have the following keys:
	// (See: https://api.slack.com/slash-commands)
	keyToken       = "token"
	keyTeamID      = "team_id"
	keyChannelId   = "channel_id"
	keyChannelName = "channel_name"
	keyUserID      = "user_id"
	keyUserName    = "user_name"
	keyCommand     = "command"
	keyText        = "text"
)

var (
	port int
	// Random animals cribbed from Google Drive's "Anonymous [Animal]" notifications
	animals = []string{
		"alligator", "anteater", "armadillo", "auroch", "axolotl", "badger", "bat", "beaver", "buffalo",
		"camel", "chameleon", "cheetah", "chipmunk", "chinchilla", "chupacabra", "cormorant", "coyote",
		"crow", "dingo", "dinosaur", "dolphin", "duck", "elephant", "ferret", "fox", "frog", "giraffe",
		"gopher", "grizzly", "hedgehog", "hippo", "hyena", "jackal", "ibex", "ifrit", "iguana", "koala",
		"kraken", "lemur", "leopard", "liger", "llama", "manatee", "mink", "monkey", "narwhal", "nyan cat",
		"orangutan", "otter", "panda", "penguin", "platypus", "python", "pumpkin", "quagga", "rabbit", "raccoon",
		"rhino", "sheep", "shrew", "skunk", "slow loris", "squirrel", "turtle", "walrus", "wolf", "wolverine", "wombat",
	}
	// Username must be first.
	payloadExp = regexp.MustCompile(`(@[^\s]+):?(.*)`)
)

// readAnonymousMessage parses the username and re-routes
// the message to the user from an anonymous animal
func readAnonymousMessage(r *http.Request) string {
	err := r.ParseForm()
	// TODO: Change HTTP status code
	if err != nil {
		return string(err.Error())
	}
	// Incoming POST's token should match the one set in Heroku
	if len(r.Form[keyToken]) == 0 || r.Form[keyToken][0] != os.Getenv(tokenConfig) {
		return "Tokens didn't match."
	}
	if len(r.Form[keyText]) == 0 {
		return ""
	}
	msg := strings.TrimSpace(r.Form[keyText][0])
	matches := payloadExp.FindStringSubmatch(msg)
	if matches == nil {
		return "Failed; message should be like: /anon @ashwin hey what's up?"
	}
	user := matches[1]
	cleanedMsg := matches[2]
	return fmt.Sprintf("Anonymously sent your message, [%s], to %s", cleanedMsg, user)
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		result := readAnonymousMessage(r)
		fmt.Fprintf(w, result)
	})
	http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

func init() {
	flag.IntVar(&port, "port", 5000, "HTTP server port")
	flag.Parse()
}
<|endoftext|>