<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"sync"
)

type database struct {
	AppServer string
	DbServer  string
	DbName    string
	User      string
	Pass      string
}

func main() {
	usr, err := user.Current()
	if err != nil {
		usage("Couldn't obtain the current user err=%v", err)
	}

	databasesFile := usr.HomeDir + "/.databases.json"
	databases := map[string]database{}

	byts, err := ioutil.ReadFile(databasesFile)
	if err != nil {
		usage("Couldn't read [%v] file. err=%v", databasesFile, err)
	}

	err = json.Unmarshal(byts, &databases)
	if err != nil {
		usage("Couldn't unmarshal [%v] file. err=%v", databasesFile, err)
	}

	if len(databases) == 0 {
		usage("Couldn't find any database configurations in [%v] file.", databasesFile)
	}

	sql := readInput(os.Stdin)
	if len(sql) <= 3 {
		usage("No SQL to run. Exiting.")
	}

	if len(os.Args[1:]) == 0 {
		usage("Target database unspecified; where should I run the query?")
	}

	targetDatabases := []string{}
	for _, k := range os.Args[1:] {
		if _, ok := databases[k]; k != "all" && !ok {
			usage("Target database unknown: [%v]", k)
		}
		if k == "all" {
			targetDatabases = nil
			for k := range databases {
				targetDatabases = append(targetDatabases, k)
			}
			break
		}
		targetDatabases = append(targetDatabases, k)
	}

	var wg sync.WaitGroup

	for _, k := range targetDatabases {
		wg.Add(1)
		go func(db database, k string) {
			defer wg.Done()
			runSQL(db, sql, k, len(targetDatabases) > 1)
		}(databases[k], k)
	}

	wg.Wait()
}

func runSQL(db database, sql string, key string, prependKey bool) {
	userOption := ""
	if db.User != "" {
		userOption = fmt.Sprintf("-u %v ", db.User)
	}

	passOption := ""
	if db.Pass != "" {
		passOption = fmt.Sprintf("-p%v ", db.Pass)
	}

	hostOption := ""
	if db.DbServer != "" {
		hostOption = fmt.Sprintf("-h %v ", db.DbServer)
	}

	prepend := ""
	if prependKey {
		prepend = key + "\t"
	}

	mysql := "mysql"
	options := fmt.Sprintf(" -Nsr %v%v%v%v -e ", userOption, passOption, hostOption, db.DbName)

	var cmd *exec.Cmd
	if db.AppServer != "" {
		query := fmt.Sprintf(`'%v'`, strings.Replace(sql, `'`, `'"'"'`, -1))
		cmd = exec.Command("ssh", db.AppServer, mysql+options+query)
	} else {
		args := append(trimEmpty(strings.Split(options, " ")), sql)
		cmd = exec.Command("mysql", args...)
	}

	cmd.Stderr = os.Stderr

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("Cannot create pipe for running command on %v; not running.\n", key)
		return
	}

	if err := cmd.Start(); err != nil {
		log.Printf("Cannot start command on %v; not running.\n", key)
		return
	}

	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		fmt.Println(prepend + scanner.Text())
	}

	if err := cmd.Wait(); err != nil {
		os.Exit(1)
	}
}

func readInput(r io.Reader) string {
	ls := []string{}
	var err error
	rd := bufio.NewReader(r)

	for {
		var s string
		s, err = rd.ReadString('\n')
		if err == io.EOF {
			return strings.Join(ls, " ")
		}
		s = strings.TrimSpace(s)
		if len(s) == 0 {
			continue
		}
		ls = append(ls, strings.TrimSpace(s))
	}
}

func trimEmpty(s []string) []string {
	var r []string
	for _, str := range s {
		if str != "" {
			r = append(r, str)
		}
	}
	return r
}
<commit_msg>Fixes bug where sql exits while other spawned queries still go on.<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"os/user"
	"strings"
	"sync"
)

type database struct {
	AppServer string
	DbServer  string
	DbName    string
	User      string
	Pass      string
}

func main() {
	usr, err := user.Current()
	if err != nil {
		usage("Couldn't obtain the current user err=%v", err)
	}

	databasesFile := usr.HomeDir + "/.databases.json"
	databases := map[string]database{}

	byts, err := ioutil.ReadFile(databasesFile)
	if err != nil {
		usage("Couldn't read [%v] file. err=%v", databasesFile, err)
	}

	err = json.Unmarshal(byts, &databases)
	if err != nil {
		usage("Couldn't unmarshal [%v] file. err=%v", databasesFile, err)
	}

	if len(databases) == 0 {
		usage("Couldn't find any database configurations in [%v] file.", databasesFile)
	}

	sql := readInput(os.Stdin)
	if len(sql) <= 3 {
		usage("No SQL to run. Exiting.")
	}

	if len(os.Args[1:]) == 0 {
		usage("Target database unspecified; where should I run the query?")
	}

	targetDatabases := []string{}
	for _, k := range os.Args[1:] {
		if _, ok := databases[k]; k != "all" && !ok {
			usage("Target database unknown: [%v]", k)
		}
		if k == "all" {
			targetDatabases = nil
			for k := range databases {
				targetDatabases = append(targetDatabases, k)
			}
			break
		}
		targetDatabases = append(targetDatabases, k)
	}

	var wg sync.WaitGroup

	for _, k := range targetDatabases {
		wg.Add(1)
		go func(db database, k string) {
			defer wg.Done()
			runSQL(db, sql, k, len(targetDatabases) > 1)
		}(databases[k], k)
	}

	wg.Wait()
}

func runSQL(db database, sql string, key string, prependKey bool) {
	userOption := ""
	if db.User != "" {
		userOption = fmt.Sprintf("-u %v ", db.User)
	}

	passOption := ""
	if db.Pass != "" {
		passOption = fmt.Sprintf("-p%v ", db.Pass)
	}

	hostOption := ""
	if db.DbServer != "" {
		hostOption = fmt.Sprintf("-h %v ", db.DbServer)
	}

	prepend := ""
	if prependKey {
		prepend = key + "\t"
	}

	mysql := "mysql"
	options := fmt.Sprintf(" -Nsr %v%v%v%v -e ", userOption, passOption, hostOption, db.DbName)

	var cmd *exec.Cmd
	if db.AppServer != "" {
		query := fmt.Sprintf(`'%v'`, strings.Replace(sql, `'`, `'"'"'`, -1))
		cmd = exec.Command("ssh", db.AppServer, mysql+options+query)
	} else {
		args := append(trimEmpty(strings.Split(options, " ")), sql)
		cmd = exec.Command("mysql", args...)
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("Cannot create pipe for STDOUT of running command on %v; not running.\n", key)
		return
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Printf("Cannot create pipe for STDERR of running command on %v; not running.\n", key)
		return
	}

	if err := cmd.Start(); err != nil {
		log.Printf("Cannot start command on %v; not running.\n", key)
		return
	}

	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		fmt.Println(prepend + scanner.Text())
	}

	stderrLines := []string{}
	scanner = bufio.NewScanner(stderr)
	for scanner.Scan() {
		stderrLines = append(stderrLines, scanner.Text())
	}

	if len(stderrLines) > 0 {
		log.Println(key + " had errors:")
		for _, v := range stderrLines {
			log.Println(key + " [ERROR] " + v)
		}
	}

	cmd.Wait()
}

func readInput(r io.Reader) string {
	ls := []string{}
	var err error
	rd := bufio.NewReader(r)

	for {
		var s string
		s, err = rd.ReadString('\n')
		if err == io.EOF {
			return strings.Join(ls, " ")
		}
		s = strings.TrimSpace(s)
		if len(s) == 0 {
			continue
		}
		ls = append(ls, strings.TrimSpace(s))
	}
}

func trimEmpty(s []string) []string {
	var r []string
	for _, str := range s {
		if str != "" {
			r = append(r, str)
		}
	}
	return r
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/DeanThompson/ginpprof"
	"github.com/Verifier/emailVerifier/constants"
	"github.com/Verifier/emailVerifier/handlers"
	"github.com/brandfolder/gin-gorelic"
	"github.com/gin-gonic/gin"
	newrelic "github.com/newrelic/go-agent"
)

const (
	apiBaseURL = "/email-verifier/api/1.0"
)

func main() {

	appKey := constants.Env.NewrelicAppKey   //newrelic app key
	appName := constants.Env.NewrelicAppName //newrelic app name

	router := gin.New() // Create a gin router without any default middleware

	// Add go-agent middleware to send profiling info to newrelic
	router.Use(newrelicMiddleware(appKey, appName))
	// Add gorelic middleware to send extra metrics to newrelic
	gorelic.InitNewrelicAgent(appKey, appName, false)
	router.Use(gorelic.Handler)
	// Add recovery (crash-free) middleware
	router.Use(gin.Recovery())
	// Add logger middleware only when running in debug mode (GIN_MODE env variable)
	if gin.Mode() == gin.DebugMode {
		router.Use(gin.Logger())
	}

	//Loading html files
	router.LoadHTMLGlob("static/*.html")
	router.Static("/css", "static/css")
	router.Static("/images", "static/images")
	router.Static("/js", "static/js")
	router.Static("/fonts", "static/fonts")

	router.GET("/ping", func(c *gin.Context) {
		c.String(http.StatusOK, "pong")
	})

	//emailVerifierClient api to verify list of emails
	emailVerifierClient := router.Group(apiBaseURL + "/emails")
	{
		emailVerifierClient.POST("/verify", handlers.VerifyEmails)
		emailVerifierClient.GET( "/index.html", handlers.GetIndexPage)
	}

	// Wrapping with pprof if running in debug mode
	if gin.Mode() == gin.DebugMode {
		ginpprof.Wrapper(router)
	}

	router.Run(":" + constants.Env.Port)
}

func newrelicMiddleware(appKey string, appName string) gin.HandlerFunc {

	if appName == "" || appKey == "" {
		return func(c *gin.Context) {}
	}

	config := newrelic.NewConfig(appName, appKey)
	app, _ := newrelic.NewApplication(config)

	return func(c *gin.Context) {
		txn := app.StartTransaction(c.Request.URL.Path, c.Writer, c.Request)
		defer txn.End()
		c.Next()
	}
}
<commit_msg>USing env variables for templates<commit_after>package main

import (
	"net/http"

	"github.com/DeanThompson/ginpprof"
	"github.com/Verifier/emailVerifier/constants"
	"github.com/Verifier/emailVerifier/handlers"
	"github.com/brandfolder/gin-gorelic"
	"github.com/gin-gonic/gin"
	newrelic "github.com/newrelic/go-agent"
	"path/filepath"
	"os"
	"fmt"
)

const (
	apiBaseURL = "/email-verifier/api/1.0"
)

func main() {

	appKey := constants.Env.NewrelicAppKey   //newrelic app key
	appName := constants.Env.NewrelicAppName //newrelic app name

	router := gin.New() // Create a gin router without any default middleware

	// Add go-agent middleware to send profiling info to newrelic
	router.Use(newrelicMiddleware(appKey, appName))
	// Add gorelic middleware to send extra metrics to newrelic
	gorelic.InitNewrelicAgent(appKey, appName, false)
	router.Use(gorelic.Handler)
	// Add recovery (crash-free) middleware
	router.Use(gin.Recovery())
	// Add logger middleware only when running in debug mode (GIN_MODE env variable)
	if gin.Mode() == gin.DebugMode {
		router.Use(gin.Logger())
	}

	//Loading html files
	//router.LoadHTMLGlob(filepath.Join(os.Getenv("TMPL_DIR"), "*"))
	staticFilePath := "~/gospace/src/github.com/Verifier/emailVerifier/static/"
	fmt.Println(os.Getenv("TEMPL_DIR"))
	router.LoadHTMLGlob(filepath.Join(os.Getenv("TEMPL_DIR"), "*.html"))
	router.Static("/css", filepath.Join(staticFilePath, "css"))
	router.Static("/images", filepath.Join(staticFilePath, "images"))
	router.Static("/js", filepath.Join(staticFilePath, "js"))
	router.Static("/fonts", filepath.Join(staticFilePath, "fonts"))

	router.GET("/ping", func(c *gin.Context) {
		c.String(http.StatusOK, "pong")
	})

	//emailVerifierClient api to verify list of emails
	emailVerifierClient := router.Group(apiBaseURL + "/emails")
	{
		emailVerifierClient.POST("/verify", handlers.VerifyEmails)
		emailVerifierClient.GET( "/index.html", handlers.GetIndexPage)
	}

	// Wrapping with pprof if running in debug mode
	if gin.Mode() == gin.DebugMode {
		ginpprof.Wrapper(router)
	}

	router.Run(":" + constants.Env.Port)
}

func newrelicMiddleware(appKey string, appName string) gin.HandlerFunc {

	if appName == "" || appKey == "" {
		return func(c *gin.Context) {}
	}

	config := newrelic.NewConfig(appName, appKey)
	app, _ := newrelic.NewApplication(config)

	return func(c *gin.Context) {
		txn := app.StartTransaction(c.Request.URL.Path, c.Writer, c.Request)
		defer txn.End()
		c.Next()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"image"

	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dimg"
)

func fontFileName(fontData draw2d.FontData) string {
	return fontData.Name + ".ttf"
}

func main() {
	draw2d.SetFontFolder("./fonts/")
	draw2d.SetFontNamer(fontFileName)

	dest := image.NewRGBA(image.Rect(0, 0, 105, 18))
	gc := draw2dimg.NewGraphicContext(dest)
	gc.FillStroke()

	gc.SetFontData(draw2d.FontData{Name: "OpenSans-Regular"})
	gc.SetFillColor(image.Black) // Text color
	gc.SetFontSize(14)
	gc.FillStringAt("0123456789", 0, 14)
	gc.Close()

	// Save to file
	draw2dimg.SaveToPngFile("digits.png", dest)
}
<commit_msg>Wrap digit drawer function. Center the digit<commit_after>package main

import (
	"image"

	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dimg"
)

func fontFileName(fontData draw2d.FontData) string {
	return fontData.Name + ".ttf"
}

func drawDigitsWithFont(digit string, fontName string, fontSize float64) image.Image {
	canvas := image.NewRGBA(image.Rect(0, 0, 28, 28))
	gc := draw2dimg.NewGraphicContext(canvas)

	gc.DrawImage(image.White)    // Background color
	gc.SetFillColor(image.Black) // Text color

	gc.SetFontData(draw2d.FontData{Name: fontName})
	gc.SetFontSize(fontSize)

	left, top, right, bottom := gc.GetStringBounds(digit)
	height := bottom - top
	width := right - left

	center := 28.0 / 2
	gc.FillStringAt(digit, center-width/2, center+height/2)

	return canvas
}

func main() {
	draw2d.SetFontFolder("./fonts/")
	draw2d.SetFontNamer(fontFileName)

	digit := drawDigitsWithFont("8", "OpenSans-Regular", 14)
	draw2dimg.SaveToPngFile("digits.png", digit)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"os/user"
	"strconv"
	"syscall"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/boltdb/bolt"
	"github.com/docker/libcontainer/netlink"
	"github.com/docker/libcontainer/network"
	"github.com/rakyll/globalconf"
)

const (
	appName       = "tentacool"
	addressBucket = "address"
)

var (
	flagSocket = flag.String("socket", "/var/run/"+appName, "Path for unix socket")
	flagOwner  = flag.String("owner", "", "Ownership for socket")
	flagGroup  = flag.Int("group", -1, "Group for socket")
	flagDB     = flag.String("db", "/var/lib/"+appName+"/db", "Path for DB")
	// flagMode   = flag.Int("mode", 0640, "FileMode for socket")

	db *bolt.DB
	ln net.Listener
)

type Address struct {
	ID   string
	Link string
	IP   string
}

func main() {
	conf, err := globalconf.New(appName)
	if err != nil {
		log.Fatal(err)
	}
	conf.ParseAll()

	handler := rest.ResourceHandler{}
	err = handler.SetRoutes(
		&rest.Route{"GET", "/interfaces", GetIfaces},
		&rest.Route{"GET", "/interfaces/:iface", GetIface},
		&rest.Route{"GET", "/addresses", GetAddresses},
		&rest.Route{"POST", "/addresses", PostAddress},
		&rest.Route{"GET", "/addresses/:address", GetAddress},
		&rest.Route{"GET", "/routes", GetRoutes},
	)
	if err != nil {
		log.Fatal(err)
	}

	ln, err = net.Listen("unix", *flagSocket)
	if nil != err {
		log.Fatal(err)
	}

	if *flagOwner != "" {
		user, err := user.Lookup(*flagOwner)
		if err != nil {
			log.Fatal(err)
		}
		uid, err := strconv.Atoi(user.Uid)
		var gid int
		if *flagGroup != -1 {
			gid = *flagGroup
		} else {
			gid, err = strconv.Atoi(user.Gid)
		}
		if err := os.Chown(*flagSocket, uid, gid); err != nil {
			log.Fatal(err)
		}
	}

	// Handle common process-killing signals so we can gracefully shut down:
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
	go func(c chan os.Signal) {
		// Wait for a SIGINT or SIGKILL:
		sig := <-c
		log.Printf("Caught signal %s: shutting down.", sig)
		// Stop listening (and unlink the socket if unix type):
		ln.Close()
		db.Close()
		os.Exit(0)
	}(sigc)

	db, err = bolt.Open(*flagDB, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	db.Update(func(tx *bolt.Tx) (err error) {
		_, err = tx.CreateBucketIfNotExists([]byte(addressBucket))
		if err != nil {
			log.Fatal(err)
		}
		return
	})

	log.Printf("Reinstall previous address from DB")
	db.View(func(tx *bolt.Tx) (err error) {
    b := tx.Bucket([]byte(addressBucket))
		address := Address{}
    b.ForEach(func(k, v []byte) (err error) {
			if err := json.Unmarshal(v, &address); err != nil {
				log.Printf(err.Error())
			}
			if err:=SetIP(address); err != nil {
        log.Printf(err.Error())
			}
			return
    })
    return
	})

	log.Fatal(http.Serve(ln, &handler))
	defer ln.Close()
}

func GetIfaces(w rest.ResponseWriter, req *rest.Request) {
	interfaces, err := net.Interfaces()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(interfaces)
}

func GetIface(w rest.ResponseWriter, req *rest.Request) {
	iface, err := net.InterfaceByName(req.PathParam("iface"))
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	ip, err := iface.Addrs()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(ip)
}

func GetAddresses(w rest.ResponseWriter, req *rest.Request) {
	addresses := []Address{}
	err := db.View(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte(addressBucket))
		address := Address{}
		b.ForEach(func(k, v []byte) (err error) {
			err = json.Unmarshal(v, &address)
			if err != nil {
				return
			}
			addresses = append(addresses, address)
			return
		})
		return
	})
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(addresses)
}

func GetAddress(w rest.ResponseWriter, req *rest.Request) {
	id := req.PathParam("address")

	address := Address{}
	db.View(func(tx *bolt.Tx) (err error) {
		tmp := tx.Bucket([]byte(addressBucket)).Get([]byte(id))
		if err = json.Unmarshal(tmp, &address); err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	})
	w.WriteJson(address)
}

func PostAddress(w rest.ResponseWriter, req *rest.Request) {
	address := Address{}
	if err := req.DecodeJsonPayload(&address); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if err := SetIP(address); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	db.Update(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte(addressBucket))
		if address.ID == "" {
			int, err := b.NextSequence()
			if err != nil {
				log.Printf(err.Error())
				rest.Error(w, err.Error(), http.StatusInternalServerError)
				return err
			}
			address.ID = strconv.FormatUint(int, 10)
		}
		data, err := json.Marshal(address)
		if err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		err = b.Put([]byte(address.ID), []byte(data))
		return
	})
	w.WriteJson(address)
}

func GetRoutes(w rest.ResponseWriter, req *rest.Request) {
	routes, err := netlink.NetworkGetRoutes()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(routes)
}

func SetIP(a Address) (err error) {
	log.Printf("Set IP:%s, to:%s", a.IP, a.Link)
	err = network.SetInterfaceIp(a.Link, a.IP)
	if err != nil {
		return
	}
	log.Printf("Adding route for this address")
	_ = netlink.AddRoute("", a.IP, "", a.Link)
	return
}
<commit_msg>Fix json key format<commit_after>package main

import (
	"encoding/json"
	"flag"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"os/user"
	"strconv"
	"syscall"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/boltdb/bolt"
	"github.com/docker/libcontainer/netlink"
	"github.com/docker/libcontainer/network"
	"github.com/rakyll/globalconf"
)

const (
	appName       = "tentacool"
	addressBucket = "address"
)

var (
	flagSocket = flag.String("socket", "/var/run/"+appName, "Path for unix socket")
	flagOwner  = flag.String("owner", "", "Ownership for socket")
	flagGroup  = flag.Int("group", -1, "Group for socket")
	flagDB     = flag.String("db", "/var/lib/"+appName+"/db", "Path for DB")
	// flagMode   = flag.Int("mode", 0640, "FileMode for socket")

	db *bolt.DB
	ln net.Listener
)

type Address struct {
	ID   string `json:"id"`
	Link string `json:"link"`
	IP   string `json:"ip"`
}

func main() {
	conf, err := globalconf.New(appName)
	if err != nil {
		log.Fatal(err)
	}
	conf.ParseAll()

	handler := rest.ResourceHandler{}
	err = handler.SetRoutes(
		&rest.Route{"GET", "/interfaces", GetIfaces},
		&rest.Route{"GET", "/interfaces/:iface", GetIface},
		&rest.Route{"GET", "/addresses", GetAddresses},
		&rest.Route{"POST", "/addresses", PostAddress},
		&rest.Route{"GET", "/addresses/:address", GetAddress},
		&rest.Route{"GET", "/routes", GetRoutes},
	)
	if err != nil {
		log.Fatal(err)
	}

	ln, err = net.Listen("unix", *flagSocket)
	if nil != err {
		log.Fatal(err)
	}

	if *flagOwner != "" {
		user, err := user.Lookup(*flagOwner)
		if err != nil {
			log.Fatal(err)
		}
		uid, err := strconv.Atoi(user.Uid)
		var gid int
		if *flagGroup != -1 {
			gid = *flagGroup
		} else {
			gid, err = strconv.Atoi(user.Gid)
		}
		if err := os.Chown(*flagSocket, uid, gid); err != nil {
			log.Fatal(err)
		}
	}

	// Handle common process-killing signals so we can gracefully shut down:
	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
	go func(c chan os.Signal) {
		// Wait for a SIGINT or SIGKILL:
		sig := <-c
		log.Printf("Caught signal %s: shutting down.", sig)
		// Stop listening (and unlink the socket if unix type):
		ln.Close()
		db.Close()
		os.Exit(0)
	}(sigc)

	db, err = bolt.Open(*flagDB, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	db.Update(func(tx *bolt.Tx) (err error) {
		_, err = tx.CreateBucketIfNotExists([]byte(addressBucket))
		if err != nil {
			log.Fatal(err)
		}
		return
	})

	log.Printf("Reinstall previous address from DB")
	db.View(func(tx *bolt.Tx) (err error) {
    b := tx.Bucket([]byte(addressBucket))
		address := Address{}
    b.ForEach(func(k, v []byte) (err error) {
			if err := json.Unmarshal(v, &address); err != nil {
				log.Printf(err.Error())
			}
			if err:=SetIP(address); err != nil {
        log.Printf(err.Error())
			}
			return
    })
    return
	})

	log.Fatal(http.Serve(ln, &handler))
	defer ln.Close()
}

func GetIfaces(w rest.ResponseWriter, req *rest.Request) {
	interfaces, err := net.Interfaces()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(interfaces)
}

func GetIface(w rest.ResponseWriter, req *rest.Request) {
	iface, err := net.InterfaceByName(req.PathParam("iface"))
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	ip, err := iface.Addrs()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(ip)
}

func GetAddresses(w rest.ResponseWriter, req *rest.Request) {
	addresses := []Address{}
	err := db.View(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte(addressBucket))
		address := Address{}
		b.ForEach(func(k, v []byte) (err error) {
			err = json.Unmarshal(v, &address)
			if err != nil {
				return
			}
			addresses = append(addresses, address)
			return
		})
		return
	})
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(addresses)
}

func GetAddress(w rest.ResponseWriter, req *rest.Request) {
	id := req.PathParam("address")

	address := Address{}
	db.View(func(tx *bolt.Tx) (err error) {
		tmp := tx.Bucket([]byte(addressBucket)).Get([]byte(id))
		if err = json.Unmarshal(tmp, &address); err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	})
	w.WriteJson(address)
}

func PostAddress(w rest.ResponseWriter, req *rest.Request) {
	address := Address{}
	if err := req.DecodeJsonPayload(&address); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if err := SetIP(address); err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	db.Update(func(tx *bolt.Tx) (err error) {
		b := tx.Bucket([]byte(addressBucket))
		if address.ID == "" {
			int, err := b.NextSequence()
			if err != nil {
				log.Printf(err.Error())
				rest.Error(w, err.Error(), http.StatusInternalServerError)
				return err
			}
			address.ID = strconv.FormatUint(int, 10)
		}
		data, err := json.Marshal(address)
		if err != nil {
			log.Printf(err.Error())
			rest.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		err = b.Put([]byte(address.ID), []byte(data))
		return
	})
	w.WriteJson(address)
}

func GetRoutes(w rest.ResponseWriter, req *rest.Request) {
	routes, err := netlink.NetworkGetRoutes()
	if err != nil {
		log.Printf(err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteJson(routes)
}

func SetIP(a Address) (err error) {
	log.Printf("Set IP:%s, to:%s", a.IP, a.Link)
	err = network.SetInterfaceIp(a.Link, a.IP)
	if err != nil {
		return
	}
	log.Printf("Adding route for this address")
	_ = netlink.AddRoute("", a.IP, "", a.Link)
	return
}
<|endoftext|>


<commit_before>package main

import "golang.org/x/sys/windows/registry"
import "github.com/pkg/errors"
import "fmt"
import "os/exec"
import "os"
import "encoding/xml"
import "time"

type DSACatalogGranulePick struct {
	XMLName        xml.Name `xml:"GranulePick"`
	PlatformType   string   `xml:"PlatformType,attr"`
	MfgCode        string   `xml:"MfgCode,attr"`
	SelectionState string   `xml:"SelectionState,attr"`
}

type DSACatalogState struct {
	XMLName          xml.Name                `xml:"StateCookieInfo"`
	UsingNetwork     bool                    `xml:"Client>NetworkInfo>IsNetworkDeployment"`
	GranulePicks     []DSACatalogGranulePick `xml:"Client>UserPicks>GranulePicks>GranulePick"`
	ServerDest       string                  `xml:"Server>Destination"`
	LastDiscLocation string
}

const (
	CAP2020_CATALOG          = `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\20-20 COMMERCIAL CATALOGS`
	CAP2020_SOFTWARE         = `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{5D4D912A-D5EE-4748-84B8-7C2C75EC4408}`
	CAP2020_SOFTWARE_CURRENT = `13.00.13037`
	PATH_CATALOG             = `\\10.0.9.29\2020catalogbeta\ClientSetup\setup.exe`
	PATH_SOFTWARE            = `\\10.0.9.29\2020software\Setup.exe`
)

const (
	CATALOG_STATE_MISSNG = iota
	CATALOG_STATE_LOCAL
	CATALOG_STATE_NETWORK
	CATALOG_STATE_INVALID
)

func GetCatalogStatus() (int, error) {
	f, err := os.Open(`C:\ProgramData\2020\DSA\2020Catalogs-StateCookie.xml`)
	if err != nil {
		// This is fine, it likely just means the software isn't installed
		return CATALOG_STATE_MISSNG, nil
	}
	defer f.Close()

	var catalogstate DSACatalogState
	dec := xml.NewDecoder(f)
	err = dec.Decode(&catalogstate)
	if err != nil {
		return CATALOG_STATE_INVALID, errors.Wrap(err, "Cannot decode DSA state XML file")
	}

	// The Demo package is mandatory for all installs, so we can check if it's selected
	// in order to determine whether anything is locally installed.
	for j := range catalogstate.GranulePicks {
		if catalogstate.GranulePicks[j].MfgCode == `DMO` &&
			catalogstate.GranulePicks[j].PlatformType == `CAP` &&
			catalogstate.GranulePicks[j].SelectionState == `Selected` {
			return CATALOG_STATE_LOCAL, nil
		}
	}

	if catalogstate.ServerDest != `\\10.0.9.29\2020catalogbeta\` {
		fmt.Printf("Catalog Server Destination is incorrectly %s\n", catalogstate.ServerDest)
		return CATALOG_STATE_INVALID, nil
	}

	if catalogstate.LastDiscLocation != `\\10.0.9.29\2020catalogbeta\ClientSetup` {
		fmt.Printf("Catalog Last Disc Location is incorrectly %s\n", catalogstate.LastDiscLocation)
		return CATALOG_STATE_INVALID, nil
	}

	return CATALOG_STATE_NETWORK, nil
}

func CleanCatalog() error {
	return os.RemoveAll(`C:\ProgramData\2020\DSA`)
}

func UninstallCatalog() error {
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, CAP2020_CATALOG, registry.READ)
	if err != nil {
		return errors.Wrap(err, "Cannot open registry key for uninstall")
	}
	defer k.Close()

	v, _, err := k.GetStringValue("UninstallString")
	if err != nil {
		return errors.Wrap(err, "Cannot read value UninstallString")
	}

	// Verify that the uninstall command looks like one we recognize.
	if v != `C:\Program Files (x86)\2020\DSA\dsa.exe /removeall /rootpath "C:\ProgramData\2020\DSA"` {
		return errors.Errorf("UninstallString had an unexpected value of %s", v)
	}

	out, err := exec.Command(`C:\Program Files (x86)\2020\DSA\dsa.exe`, "/removeall", "/rootpath", `"C:\ProgramData\2020\DSA"`).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Uninstall command output: %s", out)
	}
	return nil
}

// "Is Installed", "Is Current", error
func GetSoftwareStatus() (bool, bool, error) {
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, CAP2020_SOFTWARE, registry.READ)
	if err == registry.ErrNotExist {
		return false, false, nil
	} else if err != nil {
		return false, false, errors.Wrap(err, "Cannot open registry key for software version")
	}
	defer k.Close()

	v, _, err := k.GetStringValue("DisplayVersion")
	if err != nil {
		return false, false, errors.Wrap(err, "Cannot read value DisplayVersion")
	}

	return true, (v == CAP2020_SOFTWARE_CURRENT), nil
}

func InstallNetworkCatalog() error {
	out, err := exec.Command(PATH_CATALOG).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Setup command output: %s", out)
	}

	return nil
}

func InstallSoftware() error {
	out, err := exec.Command(PATH_SOFTWARE).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Install command output: %s", out)
	}

	return nil
}

func UninstallSoftware() error {
	out, err := exec.Command("msiexec", "/x", `{5D4D912A-D5EE-4748-84B8-7C2C75EC4408}`, "/passive", "/forcerestart").CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Uninstall command output: %s", out)
	}

	return nil
}

func ExitWithSuccess(m string) {
	fmt.Printf("SUCCESS: %s\n\n", m)
	time.Sleep(10 * time.Second)
	os.Exit(0)
}

func ExitWithError(m string, e error) {
	fmt.Printf("ERROR: %s (%+v)\n\n", m, e)
	time.Sleep(5 * time.Minute)
	os.Exit(1)
}

func ExitWithoutSuccess(m string) {
	fmt.Printf("UNSUCCESSFUL: %s\n\n", m)
	time.Sleep(5 * time.Minute)
	os.Exit(2)
}

func main() {
	var err error

	softInstalled, softCurrent, err := GetSoftwareStatus()
	if err != nil {
		ExitWithError("Unable to check software status.", err)
	}

	if !softInstalled {
		fmt.Println("2020 software is not installed.")
		err = InstallSoftware()
		if err != nil {
			ExitWithError("Unable to install the 2020 software. Restart your computer and try again manually.", err)
		}
		ExitWithoutSuccess("Complete the install process manually and run this again afterward.")
	}

	if !softCurrent {
		fmt.Println("2020 software is out of date. Uninstalling current software...")
		err = UninstallSoftware()
		if err != nil {
			ExitWithError("Unable to uninstall the 2020 software. Restart your computer and try again manually.", err)
		}
		ExitWithoutSuccess("Software uninstall will require a reboot. After reboot, run again to update software.")
	}

	fmt.Println("Looks like the 2020 software is up to date. Let's check your catalog...")

	catState, err := GetCatalogStatus()
	if err != nil {
		ExitWithError("Unable to check for Network Deployment.", err)
	}

	if catState == CATALOG_STATE_NETWORK {
		ExitWithSuccess("You are using the 2020 Network Deployment. Nice.")
	}

	if catState == CATALOG_STATE_LOCAL {
		fmt.Println("Looks like you have the catalog installed locally, not on the network.")
		fmt.Println("Uninstalling local catalog.")
		err = UninstallCatalog()
		if err != nil {
			ExitWithError("Can't run the uninstaller for the catalog. Try running it yourself.", err)
		}
		fmt.Println("Clearing out remaining files after uninstall.")
		CleanCatalog()
	}

	fmt.Println("Installing the network catalog...")
	err = InstallNetworkCatalog()
	if err != nil {
		ExitWithError("Failed to install the network catalog.", err)
	}
	fmt.Println("Checking the catalog status again...")
	catState, err = GetCatalogStatus()
	if err == nil && catState == CATALOG_STATE_NETWORK {
		ExitWithSuccess("Looks good. Network catalog is now installed.")
	}
	ExitWithoutSuccess("Finish installing the catalog by using the wizard. You can close this window.")
}
<commit_msg>rm ServerDest<commit_after>package main

import "golang.org/x/sys/windows/registry"
import "github.com/pkg/errors"
import "fmt"
import "os/exec"
import "os"
import "encoding/xml"
import "time"

type DSACatalogGranulePick struct {
	XMLName        xml.Name `xml:"GranulePick"`
	PlatformType   string   `xml:"PlatformType,attr"`
	MfgCode        string   `xml:"MfgCode,attr"`
	SelectionState string   `xml:"SelectionState,attr"`
}

type DSACatalogState struct {
	XMLName          xml.Name                `xml:"StateCookieInfo"`
	UsingNetwork     bool                    `xml:"Client>NetworkInfo>IsNetworkDeployment"`
	GranulePicks     []DSACatalogGranulePick `xml:"Client>UserPicks>GranulePicks>GranulePick"`
	LastDiscLocation string
}

const (
	CAP2020_CATALOG          = `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\20-20 COMMERCIAL CATALOGS`
	CAP2020_SOFTWARE         = `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{5D4D912A-D5EE-4748-84B8-7C2C75EC4408}`
	CAP2020_SOFTWARE_CURRENT = `13.00.13037`
	PATH_CATALOG             = `\\10.0.9.29\2020catalogbeta\ClientSetup\setup.exe`
	PATH_SOFTWARE            = `\\10.0.9.29\2020software\Setup.exe`
)

const (
	CATALOG_STATE_MISSNG = iota
	CATALOG_STATE_LOCAL
	CATALOG_STATE_NETWORK
	CATALOG_STATE_INVALID
)

func GetCatalogStatus() (int, error) {
	f, err := os.Open(`C:\ProgramData\2020\DSA\2020Catalogs-StateCookie.xml`)
	if err != nil {
		// This is fine, it likely just means the software isn't installed
		return CATALOG_STATE_MISSNG, nil
	}
	defer f.Close()

	var catalogstate DSACatalogState
	dec := xml.NewDecoder(f)
	err = dec.Decode(&catalogstate)
	if err != nil {
		return CATALOG_STATE_INVALID, errors.Wrap(err, "Cannot decode DSA state XML file")
	}

	// The Demo package is mandatory for all installs, so we can check if it's selected
	// in order to determine whether anything is locally installed.
	for j := range catalogstate.GranulePicks {
		if catalogstate.GranulePicks[j].MfgCode == `DMO` &&
			catalogstate.GranulePicks[j].PlatformType == `CAP` &&
			catalogstate.GranulePicks[j].SelectionState == `Selected` {
			return CATALOG_STATE_LOCAL, nil
		}
	}

	if catalogstate.LastDiscLocation != `\\10.0.9.29\2020catalogbeta\ClientSetup` {
		fmt.Printf("Catalog Last Disc Location is incorrectly %s\n", catalogstate.LastDiscLocation)
		return CATALOG_STATE_INVALID, nil
	}

	return CATALOG_STATE_NETWORK, nil
}

func CleanCatalog() error {
	return os.RemoveAll(`C:\ProgramData\2020\DSA`)
}

func UninstallCatalog() error {
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, CAP2020_CATALOG, registry.READ)
	if err != nil {
		return errors.Wrap(err, "Cannot open registry key for uninstall")
	}
	defer k.Close()

	v, _, err := k.GetStringValue("UninstallString")
	if err != nil {
		return errors.Wrap(err, "Cannot read value UninstallString")
	}

	// Verify that the uninstall command looks like one we recognize.
	if v != `C:\Program Files (x86)\2020\DSA\dsa.exe /removeall /rootpath "C:\ProgramData\2020\DSA"` {
		return errors.Errorf("UninstallString had an unexpected value of %s", v)
	}

	out, err := exec.Command(`C:\Program Files (x86)\2020\DSA\dsa.exe`, "/removeall", "/rootpath", `"C:\ProgramData\2020\DSA"`).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Uninstall command output: %s", out)
	}
	return nil
}

// "Is Installed", "Is Current", error
func GetSoftwareStatus() (bool, bool, error) {
	k, err := registry.OpenKey(registry.LOCAL_MACHINE, CAP2020_SOFTWARE, registry.READ)
	if err == registry.ErrNotExist {
		return false, false, nil
	} else if err != nil {
		return false, false, errors.Wrap(err, "Cannot open registry key for software version")
	}
	defer k.Close()

	v, _, err := k.GetStringValue("DisplayVersion")
	if err != nil {
		return false, false, errors.Wrap(err, "Cannot read value DisplayVersion")
	}

	return true, (v == CAP2020_SOFTWARE_CURRENT), nil
}

func InstallNetworkCatalog() error {
	out, err := exec.Command(PATH_CATALOG).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Setup command output: %s", out)
	}

	return nil
}

func InstallSoftware() error {
	out, err := exec.Command(PATH_SOFTWARE).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Install command output: %s", out)
	}

	return nil
}

func UninstallSoftware() error {
	out, err := exec.Command("msiexec", "/x", `{5D4D912A-D5EE-4748-84B8-7C2C75EC4408}`, "/passive", "/forcerestart").CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "Uninstall command output: %s", out)
	}

	return nil
}

func ExitWithSuccess(m string) {
	fmt.Printf("SUCCESS: %s\n\n", m)
	time.Sleep(10 * time.Second)
	os.Exit(0)
}

func ExitWithError(m string, e error) {
	fmt.Printf("ERROR: %s (%+v)\n\n", m, e)
	time.Sleep(5 * time.Minute)
	os.Exit(1)
}

func ExitWithoutSuccess(m string) {
	fmt.Printf("UNSUCCESSFUL: %s\n\n", m)
	time.Sleep(5 * time.Minute)
	os.Exit(2)
}

func main() {
	var err error

	softInstalled, softCurrent, err := GetSoftwareStatus()
	if err != nil {
		ExitWithError("Unable to check software status.", err)
	}

	if !softInstalled {
		fmt.Println("2020 software is not installed.")
		err = InstallSoftware()
		if err != nil {
			ExitWithError("Unable to install the 2020 software. Restart your computer and try again manually.", err)
		}
		ExitWithoutSuccess("Complete the install process manually and run this again afterward.")
	}

	if !softCurrent {
		fmt.Println("2020 software is out of date. Uninstalling current software...")
		err = UninstallSoftware()
		if err != nil {
			ExitWithError("Unable to uninstall the 2020 software. Restart your computer and try again manually.", err)
		}
		ExitWithoutSuccess("Software uninstall will require a reboot. After reboot, run again to update software.")
	}

	fmt.Println("Looks like the 2020 software is up to date. Let's check your catalog...")

	catState, err := GetCatalogStatus()
	if err != nil {
		ExitWithError("Unable to check for Network Deployment.", err)
	}

	if catState == CATALOG_STATE_NETWORK {
		ExitWithSuccess("You are using the 2020 Network Deployment. Nice.")
	}

	if catState == CATALOG_STATE_LOCAL {
		fmt.Println("Looks like you have the catalog installed locally, not on the network.")
		fmt.Println("Uninstalling local catalog.")
		err = UninstallCatalog()
		if err != nil {
			ExitWithError("Can't run the uninstaller for the catalog. Try running it yourself.", err)
		}
		fmt.Println("Clearing out remaining files after uninstall.")
		CleanCatalog()
	}

	fmt.Println("Installing the network catalog...")
	err = InstallNetworkCatalog()
	if err != nil {
		ExitWithError("Failed to install the network catalog.", err)
	}
	fmt.Println("Checking the catalog status again...")
	catState, err = GetCatalogStatus()
	if err == nil && catState == CATALOG_STATE_NETWORK {
		ExitWithSuccess("Looks good. Network catalog is now installed.")
	}
	ExitWithoutSuccess("Finish installing the catalog by using the wizard. You can close this window.")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"time"

	"gopkg.in/telegram-bot-api.v4"
	"gopkg.in/yaml.v2"
)

const WEATHER = "Погода в %s на %s\nТемпература: %.1f°C (%.1f°C..%.1f°C)\nДавление: %d мм/рт.с\nВлажность: %d%%\nВетер: %s %.1f м/с"

type c struct {
	Bot struct {
		Username string `yaml:"username"`
		Token    string `yaml:"token"`
	}
	Weather struct {
		City  string `yaml:"city"`
		Token string `yaml:"token"`
	}
}

type w struct {
	Coord struct {
		Lon float64
		Lat float64
	}
	Weather []struct {
		Id          int64
		Main        string
		Description string
		Icon        string
	}
	Base string
	Main struct {
		Temp     float64
		Pressure int64
		Humidity int64
		Temp_min float64
		Temp_max float64
	}
	Wind struct {
		Speed float64
		Deg   int64
	}
	Clouds struct {
		All int64
	}
	Rain struct {
		_3h int64
	}
	Dt  int64
	Sys struct {
		Type    int64
		Id      int64
		Message float64
		Country string
		Sunrise int64
		Sunset  int64
	}
	Id   int64
	Name string
	Cod  int64
}

func readconfig(data string) c {
	out := c{}
	err := yaml.Unmarshal([]byte(data), &out)
	if err != nil {
		log.Fatalf("Wrong config data.")
	}
	return out
}

func main() {
	cdata, err := ioutil.ReadFile(".config.yml")
	conf := readconfig(string(cdata))
	bot, err := tgbotapi.NewBotAPI(conf.Bot.Token)
	if err != nil {
		log.Panic(err)
	}

	bot.Debug = false

	log.Printf("Authorized on account %s", bot.Self.UserName)

	ucfg := tgbotapi.NewUpdate(0)
	ucfg.Timeout = 60

	updates, err := bot.GetUpdatesChan(ucfg)
	for {
		select {
		case update := <-updates:
			UserName := update.Message.From.UserName
			UserID := update.Message.From.ID
			ChatID := update.Message.Chat.ID
			Text := update.Message.Text

			log.Printf("%s %d %d <- %s", UserName, UserID, ChatID, Text)

			var reply string
			var quote bool

			/*			if update.Message.NewChatMember.UserName != "" {
						reply = fmt.Sprintf(`Привет @%s! Ты чего сюда припёрся?`, update.Message.NewChatMember.UserName)
						quote = false
					}*/

			switch Text {
			case "/weather":
				{
					var weather w
					resp, err := http.Get(fmt.Sprintf("http://api.openweathermap.org/data/2.5/weather?units=metric&id=%s&APPID=%s", conf.Weather.City, conf.Weather.Token))
					if err != nil {
						log.Println(err)
						reply = "No data."
					}
					body, err := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					if err != nil {
						log.Println(err)
						reply = "No data."
					}
					err = json.Unmarshal([]byte(body), &weather)
					if err != nil {
						log.Println(err)
						reply = "No data."
					}
					//					fmt.Println(string(body))
					//					fmt.Println(weather)
					reply = fmt.Sprintf(
						WEATHER,
						weather.Name,
						time.Unix(weather.Dt, 0),
						weather.Main.Temp,
						weather.Main.Temp_min,
						weather.Main.Temp_max,
						int64(float64(weather.Main.Pressure)/1.333224),
						weather.Main.Humidity,
						winddirection(weather.Wind.Deg),
						weather.Wind.Speed,
					)
				}
			case "/stocks":
				{
					resp, err := http.Get("http://finance.yahoo.com/d/quotes.csv?s=MAIL.IL&f=l1p2")
					if err != nil {
						reply = "No data."
					}
					body, err := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					if err != nil {
						reply = "No data."
					}
					reply = fmt.Sprintf("%s", body)
				}
			case "/photo":
				{

				}
			default:
				{

				}
			}

			if reply != "" {
				msg := tgbotapi.NewMessage(ChatID, reply)
				if quote {
					msg.ReplyToMessageID = update.Message.MessageID
				}
				log.Printf("%s %d %d -> %s", UserName, UserID, ChatID, reply)
				bot.Send(msg)
			}
		}
	}

	/*	for update := range updates {
		if update.Message == nil {
			continue
		}

		log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)

		msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
		msg.ReplyToMessageID = update.Message.MessageID

		bot.Send(msg)
	}*/
}

func winddirection(i int64) string {
	winds := map[int]string{
		0:   "С",
		22:  "ССВ",
		45:  "СВ",
		67:  "ВСВ",
		90:  "В",
		112: "ВЮВ",
		135: "ЮВ",
		157: "ЮЮВ",
		180: "Ю",
		202: "ЮЮЗ",
		225: "ЮЗ",
		247: "ЗЮЗ",
		270: "З",
		292: "ЗСЗ",
		315: "СЗ",
		337: "ССЗ",
		360: "С",
	}
	var keys []int
	for k := range winds {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	for _, k := range keys {
		if k >= int(i) {
			return winds[k]
		}
	}
	return ""
}
<commit_msg>optimize main()<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"time"

	"gopkg.in/telegram-bot-api.v4"
	"gopkg.in/yaml.v2"
)

const WEATHER = "Погода в %s на %s\nТемпература: %.1f°C (%.1f°C..%.1f°C)\nДавление: %d мм/рт.с\nВлажность: %d%%\nВетер: %s %.1f м/с"

type c struct {
	Bot struct {
		Username string `yaml:"username"`
		Token    string `yaml:"token"`
	}
	Weather struct {
		City  string `yaml:"city"`
		Token string `yaml:"token"`
	}
}

type w struct {
	Coord struct {
		Lon float64
		Lat float64
	}
	Weather []struct {
		Id          int64
		Main        string
		Description string
		Icon        string
	}
	Base string
	Main struct {
		Temp     float64
		Pressure int64
		Humidity int64
		Temp_min float64
		Temp_max float64
	}
	Wind struct {
		Speed float64
		Deg   int64
	}
	Clouds struct {
		All int64
	}
	Rain struct {
		_3h int64
	}
	Dt  int64
	Sys struct {
		Type    int64
		Id      int64
		Message float64
		Country string
		Sunrise int64
		Sunset  int64
	}
	Id   int64
	Name string
	Cod  int64
}

func main() {
	cdata, err := ioutil.ReadFile(".config.yml")
	conf := readconfig(string(cdata))
	bot, err := tgbotapi.NewBotAPI(conf.Bot.Token)
	if err != nil {
		log.Panic(err)
	}

	bot.Debug = false

	log.Printf("Authorized on account %s", bot.Self.UserName)

	ucfg := tgbotapi.NewUpdate(0)
	ucfg.Timeout = 60

	updates, err := bot.GetUpdatesChan(ucfg)
	for {
		select {
		case update := <-updates:
			UserName := update.Message.From.UserName
			UserID := update.Message.From.ID
			ChatID := update.Message.Chat.ID
			Text := update.Message.Text

			log.Printf("%s %d %d <- %s", UserName, UserID, ChatID, Text)

			var reply string
			var quote bool

			/*			if update.Message.NewChatMember.UserName != "" {
						reply = fmt.Sprintf(`Привет @%s! Ты чего сюда припёрся?`, update.Message.NewChatMember.UserName)
						quote = false
					}*/

			switch Text {
			case "/weather":
				{
					reply = getweather(reply, conf)
				}
			case "/stocks":
				{
					reply = getstocks(reply)
				}
			case "/photo":
				{
					reply = getphoto(reply)
				}
			default:
				{

				}
			}

			if reply != "" {
				msg := tgbotapi.NewMessage(ChatID, reply)
				if quote {
					msg.ReplyToMessageID = update.Message.MessageID
				}
				log.Printf("%s %d %d -> %s", UserName, UserID, ChatID, reply)
				bot.Send(msg)
			}
		}
	}
}

func readconfig(data string) c {
	out := c{}
	err := yaml.Unmarshal([]byte(data), &out)
	if err != nil {
		log.Fatalf("Wrong config data.")
	}
	return out
}

func winddirection(i int64) string {
	winds := map[int]string{
		0:   "С",
		22:  "ССВ",
		45:  "СВ",
		67:  "ВСВ",
		90:  "В",
		112: "ВЮВ",
		135: "ЮВ",
		157: "ЮЮВ",
		180: "Ю",
		202: "ЮЮЗ",
		225: "ЮЗ",
		247: "ЗЮЗ",
		270: "З",
		292: "ЗСЗ",
		315: "СЗ",
		337: "ССЗ",
		360: "С",
	}
	var keys []int
	for k := range winds {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	for _, k := range keys {
		if k >= int(i) {
			return winds[k]
		}
	}
	return ""
}

func getweather(reply string, conf c) string {
	var weather w
	resp, err := http.Get(fmt.Sprintf("http://api.openweathermap.org/data/2.5/weather?units=metric&id=%s&APPID=%s", conf.Weather.City, conf.Weather.Token))
	if err != nil {
		log.Println(err)
		reply = "No data."
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		log.Println(err)
		reply = "No data."
	}
	err = json.Unmarshal([]byte(body), &weather)
	if err != nil {
		log.Println(err)
		reply = "No data."
	}
	reply = fmt.Sprintf(
		WEATHER,
		weather.Name,
		time.Unix(weather.Dt, 0),
		weather.Main.Temp,
		weather.Main.Temp_min,
		weather.Main.Temp_max,
		int64(float64(weather.Main.Pressure)/1.333224),
		weather.Main.Humidity,
		winddirection(weather.Wind.Deg),
		weather.Wind.Speed,
	)
	return reply
}

func getstocks(reply string) string {
	resp, err := http.Get("http://finance.yahoo.com/d/quotes.csv?s=MAIL.IL&f=l1p2")
	if err != nil {
		reply = "No data."
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		reply = "No data."
	}
	reply = fmt.Sprintf("%s", body)
	return reply
}

func getphoto(reply string) string {
	return reply
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var configFile = flag.String("config", "", "")

type Config struct {
	Files   []Action `json:"files"`
	Command string   `json:"command"`
	Args    []string `json:"args"`
}

type Action struct {
	Type        string `json:"type"`
	Source      string `json:"source"`
	Destination string `json:"destination"`
}

func main() {
	flag.Parse()
	if *configFile == "" {
		log.Println("-config flag is not set, trying catalyst.json in current working direcotry")
		*configFile = "catalyst.json"
	}
	f, err := os.Open(*configFile)
	if err != nil {
		log.Fatal(err)
	}
	var config Config
	dec := json.NewDecoder(f)
	err = dec.Decode(&config)
	if err != nil {
		log.Fatal(err)
	}
	f.Close()
	root, err := catalystDir()
	if err != nil {
		log.Fatal(err)
	}
	err = os.Mkdir(root, 0755)
	if err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}
	for _, file := range config.Files {
		src := file.Source
		dst := filepath.Join(root, file.Destination)
		if _, err := os.Stat(dst); err == nil {
			log.Println("File exists: ", dst)
			continue
		}
		log.Println("Downloading", src)
		tmp, err := ioutil.TempFile("", "catalyst-")
		if err != nil {
			log.Fatal(err)
		}
		resp, err := http.Get(src)
		if err != nil {
			log.Fatal(err)
		}
		_, err = io.Copy(tmp, resp.Body)
		if err != nil {
			log.Fatal(err)
		}
		resp.Body.Close()
		if resp.Header.Get("Content-Type") == "application/zip" {
			log.Println("Extracting zip file")
			_, err = tmp.Seek(0, os.SEEK_SET)
			if err != nil {
				log.Fatal(err)
			}
			fi, err := tmp.Stat()
			if err != nil {
				log.Fatal(err)
			}
			err = os.Mkdir(dst, 0755)
			if err != nil && !os.IsExist(err) {
				log.Fatal(err)
			}
			r, err := zip.NewReader(tmp, fi.Size())
			if err != nil {
				log.Fatal(err)
			}
			for _, f := range r.File {
				log.Println(f.Name)
				name := filepath.Join(dst, f.Name)
				fi := f.FileInfo()
				if fi.IsDir() {
					err = os.Mkdir(name, 0755)
					if err != nil {
						log.Fatal(err)
					}
				} else {
					srcfile, err := f.Open()
					if err != nil {
						log.Fatal(err)
					}
					dstfile, err := os.Create(name)
					if err != nil {
						log.Fatal(err)
					}
					_, err = io.CopyN(dstfile, srcfile, fi.Size())
					if err != nil {
						log.Fatal(err)
					}
					err = dstfile.Close()
					if err != nil {
						log.Fatal(err)
					}
					srcfile.Close()
				}
			}
			tmp.Close()
			os.Remove(tmp.Name())
		} else {
			tmp.Close()
			err = os.Rename(tmp.Name(), dst)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
	for i := range config.Args {
		config.Args[i] = strings.Replace(config.Args[i], "$CATALYST_DIR", root, -1)
	}
	cmd := exec.Command(config.Command, config.Args...)
	err = cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>replace ${BUNDLE_DIR}<commit_after>package main

import (
	"archive/zip"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/kardianos/osext"
)

var configFile = flag.String("config", "", "")

type Config struct {
	Files   []Action `json:"files"`
	Command string   `json:"command"`
	Args    []string `json:"args"`
}

type Action struct {
	Type        string `json:"type"`
	Source      string `json:"source"`
	Destination string `json:"destination"`
}

func main() {
	flag.Parse()
	execFolder, err := osext.ExecutableFolder()
	if err != nil {
		log.Fatal(err)
	}
	parts := filepath.SplitList(execFolder)
	bundleDir := "${BUNDLE_DIR}"
	if len(parts) >= 2 {
		bundleDir = filepath.Join(parts[0 : len(parts)-2]...)
	}
	if *configFile == "" {
		log.Println("-config flag is not set, trying catalyst.json near binary")
		*configFile = filepath.Join(execFolder, "catalyst.json")
	}
	f, err := os.Open(*configFile)
	if err != nil {
		log.Fatal(err)
	}
	var config Config
	dec := json.NewDecoder(f)
	err = dec.Decode(&config)
	if err != nil {
		log.Fatal(err)
	}
	f.Close()
	root, err := catalystDir()
	if err != nil {
		log.Fatal(err)
	}
	err = os.Mkdir(root, 0755)
	if err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}
	for _, file := range config.Files {
		src := file.Source
		dst := filepath.Join(root, file.Destination)
		if _, err := os.Stat(dst); err == nil {
			log.Println("File exists: ", dst)
			continue
		}
		log.Println("Downloading", src)
		tmp, err := ioutil.TempFile("", "catalyst-")
		if err != nil {
			log.Fatal(err)
		}
		resp, err := http.Get(src)
		if err != nil {
			log.Fatal(err)
		}
		_, err = io.Copy(tmp, resp.Body)
		if err != nil {
			log.Fatal(err)
		}
		resp.Body.Close()
		if resp.Header.Get("Content-Type") == "application/zip" {
			log.Println("Extracting zip file")
			_, err = tmp.Seek(0, os.SEEK_SET)
			if err != nil {
				log.Fatal(err)
			}
			fi, err := tmp.Stat()
			if err != nil {
				log.Fatal(err)
			}
			err = os.Mkdir(dst, 0755)
			if err != nil && !os.IsExist(err) {
				log.Fatal(err)
			}
			r, err := zip.NewReader(tmp, fi.Size())
			if err != nil {
				log.Fatal(err)
			}
			for _, f := range r.File {
				log.Println(f.Name)
				name := filepath.Join(dst, f.Name)
				fi := f.FileInfo()
				if fi.IsDir() {
					err = os.Mkdir(name, 0755)
					if err != nil {
						log.Fatal(err)
					}
				} else {
					srcfile, err := f.Open()
					if err != nil {
						log.Fatal(err)
					}
					dstfile, err := os.Create(name)
					if err != nil {
						log.Fatal(err)
					}
					_, err = io.CopyN(dstfile, srcfile, fi.Size())
					if err != nil {
						log.Fatal(err)
					}
					err = dstfile.Close()
					if err != nil {
						log.Fatal(err)
					}
					srcfile.Close()
				}
			}
			tmp.Close()
			os.Remove(tmp.Name())
		} else {
			tmp.Close()
			err = os.Rename(tmp.Name(), dst)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
	for i := range config.Args {
		config.Args[i] = strings.Replace(config.Args[i], "${CATALYST_DIR}", root, -1)
		config.Args[i] = strings.Replace(config.Args[i], "${BUNDLE_DIR}", bundleDir, -1)
	}
	cmd := exec.Command(config.Command, config.Args...)
	err = cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"gopkg.in/yaml.v2"
)

type response struct {
	DayEntries []entry `json:"day_entries"`
}

type entry struct {
	Hours float64
}

type config struct {
	Email     string
	Password  string
	Subdomain string
}

var configPath = flag.String("config", "./config.yml", "path to config file")
var currentOnly = flag.Bool("o", false, "only show current time")

const harvestURL = "harvestapp.com/daily"

func createRequest(c *config) *http.Request {
	url := fmt.Sprintf("https://%s.%s", c.Subdomain, harvestURL)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}
	req.SetBasicAuth(c.Email, c.Password)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	return req
}

func main() {
	flag.Parse()
	f, err := os.Open(*configPath)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	configBytes, err := ioutil.ReadAll(f)
	if err != nil {
		panic(err)
	}

	c := config{}
	err = yaml.Unmarshal(configBytes, &c)
	if err != nil {
		panic(err)
	}

	client := &http.Client{}
	request := createRequest(&c)
	res, err := client.Do(request)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	data := response{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		panic(err)
	}

	var sum float64
	if *currentOnly {
		entry := data.DayEntries[len(data.DayEntries)-1]
		sum = entry.Hours
	} else {
		for _, entry := range data.DayEntries {
			sum += entry.Hours
		}
	}
	fmt.Printf("%1.2f", sum)
}
<commit_msg>Add current project name, time, no timer running, total<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"time"

	"gopkg.in/yaml.v2"
)

type response struct {
	DayEntries []Entry `json:"day_entries"`
}

type Entry struct {
	Client            string      `json:"client"`
	CreatedAt         time.Time   `json:"created_at"`
	Hours             float64     `json:"hours"`
	HoursWithoutTimer float64     `json:"hours_without_timer"`
	ID                int         `json:"id"`
	Notes             interface{} `json:"notes"`
	Project           string      `json:"project"`
	ProjectID         string      `json:"project_id"`
	SpentAt           string      `json:"spent_at"`
	Task              string      `json:"task"`
	TimerStartedAt    *time.Time  `json:"timer_started_at"`
	TaskID            string      `json:"task_id"`
	UpdatedAt         time.Time   `json:"updated_at"`
	UserID            int         `json:"user_id"`
}

type config struct {
	Email     string
	Password  string
	Subdomain string
}

var configPath = flag.String("config", "./config.yml", "path to config file")
var currentOnly = flag.Bool("o", false, "only show current time")

const harvestURL = "harvestapp.com/daily?slim=1"

func createRequest(c *config) *http.Request {
	url := fmt.Sprintf("https://%s.%s", c.Subdomain, harvestURL)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		panic(err)
	}
	req.SetBasicAuth(c.Email, c.Password)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	return req
}

func main() {
	flag.Parse()
	f, err := os.Open(*configPath)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	configBytes, err := ioutil.ReadAll(f)
	if err != nil {
		panic(err)
	}

	c := config{}
	err = yaml.Unmarshal(configBytes, &c)
	if err != nil {
		panic(err)
	}

	client := &http.Client{}
	request := createRequest(&c)
	res, err := client.Do(request)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	data := response{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		panic(err)
	}

	var sum float64
	for _, e := range data.DayEntries {
		sum += e.Hours
	}

	for _, e := range data.DayEntries {
		if e.TimerStartedAt != nil {
			fmt.Printf("%s — %1.2f - %1.2f", e.Client, e.Hours, sum)
			return
		}
	}
	fmt.Printf("No Timer Running!")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

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

	"github.com/docker/swarm/discovery"
	_ "github.com/docker/swarm/discovery/consul"
	_ "github.com/docker/swarm/discovery/etcd"
	_ "github.com/docker/swarm/discovery/file"
	_ "github.com/docker/swarm/discovery/nodes"
	"github.com/docker/swarm/discovery/token"
	_ "github.com/docker/swarm/discovery/zookeeper"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarm"
	app.Usage = "a Docker-native clustering system"
	app.Version = "0.1.0"
	app.Author = ""
	app.Email = ""

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:   "debug",
			Usage:  "debug mode",
			EnvVar: "DEBUG",
		},
	}

	// logs
	app.Before = func(c *cli.Context) error {
		log.SetOutput(os.Stderr)
		if c.Bool("debug") {
			log.SetLevel(log.DebugLevel)
		}
		return nil
	}

	app.Commands = []cli.Command{
		{
			Name:      "create",
			ShortName: "c",
			Usage:     "create a cluster",
			Action: func(c *cli.Context) {
				discovery := &token.TokenDiscoveryService{}
				discovery.Initialize("", 0)
				token, err := discovery.CreateCluster()
				if err != nil {
					log.Fatal(err)
				}
				fmt.Println(token)
			},
		},
		{
			Name:      "list",
			ShortName: "l",
			Usage:     "list nodes in a cluster",
			Action: func(c *cli.Context) {
				dflag := getDiscovery(c)
				if dflag == "" {
					log.Fatal("discovery required to list a cluster. See 'swarm list --help'.")
				}

				d, err := discovery.New(dflag, 0)
				if err != nil {
					log.Fatal(err)
				}

				nodes, err := d.Fetch()
				if err != nil {
					log.Fatal(err)
				}
				for _, node := range nodes {
					fmt.Println(node)
				}
			},
		},
		{
			Name:      "manage",
			ShortName: "m",
			Usage:     "manage a docker cluster",
			Flags: []cli.Flag{
				flStore,
				flStrategy, flFilter,
				flHosts, flHeartBeat, flOverCommit,
				flTls, flTlsCaCert, flTlsCert, flTlsKey, flTlsVerify,
				flEnableCors},
			Action: manage,
		},
		{
			Name:      "join",
			ShortName: "j",
			Usage:     "join a docker cluster",
			Flags:     []cli.Flag{flAddr, flHeartBeat},
			Action:    join,
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Replace --debug with --log-level<commit_after>package main

import (
	"fmt"
	"os"

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

	"github.com/docker/swarm/discovery"
	_ "github.com/docker/swarm/discovery/consul"
	_ "github.com/docker/swarm/discovery/etcd"
	_ "github.com/docker/swarm/discovery/file"
	_ "github.com/docker/swarm/discovery/nodes"
	"github.com/docker/swarm/discovery/token"
	_ "github.com/docker/swarm/discovery/zookeeper"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarm"
	app.Usage = "a Docker-native clustering system"
	app.Version = "0.1.0"
	app.Author = ""
	app.Email = ""

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "log-level, l",
			Value: "info",
			Usage: fmt.Sprintf("Log level (options: debug, info, warn, error, fatal, panic)"),
		},
	}

	// logs
	app.Before = func(c *cli.Context) error {
		log.SetOutput(os.Stderr)
		level, err := log.ParseLevel(c.String("log-level"))
		if err != nil {
			log.Fatalf(err.Error())
		}
		log.SetLevel(level)
		return nil
	}

	app.Commands = []cli.Command{
		{
			Name:      "create",
			ShortName: "c",
			Usage:     "create a cluster",
			Action: func(c *cli.Context) {
				discovery := &token.TokenDiscoveryService{}
				discovery.Initialize("", 0)
				token, err := discovery.CreateCluster()
				if err != nil {
					log.Fatal(err)
				}
				fmt.Println(token)
			},
		},
		{
			Name:      "list",
			ShortName: "l",
			Usage:     "list nodes in a cluster",
			Action: func(c *cli.Context) {
				dflag := getDiscovery(c)
				if dflag == "" {
					log.Fatal("discovery required to list a cluster. See 'swarm list --help'.")
				}

				d, err := discovery.New(dflag, 0)
				if err != nil {
					log.Fatal(err)
				}

				nodes, err := d.Fetch()
				if err != nil {
					log.Fatal(err)
				}
				for _, node := range nodes {
					fmt.Println(node)
				}
			},
		},
		{
			Name:      "manage",
			ShortName: "m",
			Usage:     "manage a docker cluster",
			Flags: []cli.Flag{
				flStore,
				flStrategy, flFilter,
				flHosts, flHeartBeat, flOverCommit,
				flTls, flTlsCaCert, flTlsCert, flTlsKey, flTlsVerify,
				flEnableCors},
			Action: manage,
		},
		{
			Name:      "join",
			ShortName: "j",
			Usage:     "join a docker cluster",
			Flags:     []cli.Flag{flAddr, flHeartBeat},
			Action:    join,
		},
	}

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


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"io/ioutil"
	"encoding/json"
	"strings"
	"github.com/line/line-bot-sdk-go/linebot"
	"github.com/go-redis/redis"
	"strconv"
	"time"
)

type device struct {
	// Gps_num float32 `json:"gps_num"`
	// App string `json:"app"`
	// Gps_alt float32 `json:"gps_alt"`
	// Fmt_opt int `json:"fmt_opt"`
	// Device string `json:"device"`
	// S_d2 float32 `json:"s_d2"`
	S_d0 float32 `json:"s_d0"`
	// S_d1 float32 `json:"s_d1"`
	S_h0 float32 `json:"s_h0"`
	SiteName string `json:"SiteName"`
	// Gps_fix float32 `json:"gps_fix"`
	// Ver_app string `json:"ver_app"`
	Gps_lat float32 `json:"gps_lat"`
	S_t0 float32 `json:"s_t0"`
	Timestamp string `json:"timestamp"`
	Gps_lon float32 `json:"gps_lon"`
	// Date string `json:"date"`
	// Tick float32 `json:"tick"`
	Device_id string `json:"device_id"`
	// S_1 float32 `json:"s_1"`
	// S_0 float32 `json:"s_0"`
	// S_3 float32 `json:"s_3"`
	// S_2 float32 `json:"s_2"`
	// Ver_format string `json:"ver_format"`
	// Time string `json:"time"`
}

type airbox struct {
	Source string `json:"source"`
	Feeds []device `json:"feeds"`
	Version string `json:"version"`
	Num_of_records int `json:"num_of_records"`
}

var bot *linebot.Client
var airbox_json airbox
var	client=redis.NewClient(&redis.Options{
		Addr:"hipposerver.ddns.net:6379",
		Password:"",
		DB:0,
	})

func main() {
	url := "https://data.lass-net.org/data/last-all-airbox.json"
	req, _ := http.NewRequest("GET", url, nil)
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)
	errs := json.Unmarshal(body, &airbox_json)
	if errs != nil {
		fmt.Println(errs)
	}
	pushmessage()
	// fmt.Println(airbox_json)
	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 pushmessage(){
	_,err:=bot.PushMessage("U3617adbdd46283d7e859f36302f4f471", linebot.NewTextMessage("hi!")).Do()
	if err!=nil{
		panic(err)
	}
}
func callbackHandler(w http.ResponseWriter, r *http.Request) {
	// t:=time.Now()
	// _, min, _:=t.Clock()
	// if min==0{
	// 	pushmessage()
	// }
	// 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:
				var txtmessage string
				inText := strings.ToLower(message.Text)
				if strings.Contains(inText,"訂閱"){
					userID:=event.Source.UserID
					// pong, _ := client.Ping().Result()
					// txtmessage=pong
					for i:=0; i<len(airbox_json.Feeds); i++ {
						if strings.Contains(inText,strings.ToLower(airbox_json.Feeds[i].Device_id)) {
							val, err:=client.Get(airbox_json.Feeds[i].Device_id).Result()
							if err!=nil{
								client.Set(airbox_json.Feeds[i].Device_id,userID,0)
								txtmessage="訂閱成功!"
								break
							}
							stringSlice:=strings.Split(val,",")
							if stringInSlice(userID,stringSlice){
								txtmessage="您已訂閱過此ID!"
								break
							} else{
								val=val+","+userID
								client.Set(airbox_json.Feeds[i].Device_id,val,0)
								txtmessage="訂閱成功!"
								break
							}
						}
					}
				} else{
					for i:=0; i<len(airbox_json.Feeds); i++ {
						if strings.Contains(inText,strings.ToLower(airbox_json.Feeds[i].Device_id)) {
							txtmessage="Device_id: "+airbox_json.Feeds[i].Device_id+"\n"
							txtmessage=txtmessage+"Site Name: "+airbox_json.Feeds[i].SiteName+"\n"
							txtmessage=txtmessage+"Location: ("+strconv.FormatFloat(float64(airbox_json.Feeds[i].Gps_lon),'f',3,64)+","+strconv.FormatFloat(float64(airbox_json.Feeds[i].Gps_lat),'f',3,64)+")"+"\n"
							txtmessage=txtmessage+"Timestamp: "+airbox_json.Feeds[i].Timestamp+"\n"
							txtmessage=txtmessage+"PM2.5: "+strconv.FormatFloat(float64(airbox_json.Feeds[i].S_d0),'f',0,64)+"\n"
							txtmessage=txtmessage+"Humidity: "+strconv.FormatFloat(float64(airbox_json.Feeds[i].S_h0),'f',0,64)+"\n"
							txtmessage=txtmessage+"Temperature: "+strconv.FormatFloat(float64(airbox_json.Feeds[i].S_t0),'f',0,64)
							break
						}
					}
				}
				if len(txtmessage)==0{
					txtmessage="Sorry! No this device ID, please check again."
				}
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(txtmessage)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}
<commit_msg>remove time<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"io/ioutil"
	"encoding/json"
	"strings"
	"github.com/line/line-bot-sdk-go/linebot"
	"github.com/go-redis/redis"
	"strconv"
	// "time"
)

type device struct {
	// Gps_num float32 `json:"gps_num"`
	// App string `json:"app"`
	// Gps_alt float32 `json:"gps_alt"`
	// Fmt_opt int `json:"fmt_opt"`
	// Device string `json:"device"`
	// S_d2 float32 `json:"s_d2"`
	S_d0 float32 `json:"s_d0"`
	// S_d1 float32 `json:"s_d1"`
	S_h0 float32 `json:"s_h0"`
	SiteName string `json:"SiteName"`
	// Gps_fix float32 `json:"gps_fix"`
	// Ver_app string `json:"ver_app"`
	Gps_lat float32 `json:"gps_lat"`
	S_t0 float32 `json:"s_t0"`
	Timestamp string `json:"timestamp"`
	Gps_lon float32 `json:"gps_lon"`
	// Date string `json:"date"`
	// Tick float32 `json:"tick"`
	Device_id string `json:"device_id"`
	// S_1 float32 `json:"s_1"`
	// S_0 float32 `json:"s_0"`
	// S_3 float32 `json:"s_3"`
	// S_2 float32 `json:"s_2"`
	// Ver_format string `json:"ver_format"`
	// Time string `json:"time"`
}

type airbox struct {
	Source string `json:"source"`
	Feeds []device `json:"feeds"`
	Version string `json:"version"`
	Num_of_records int `json:"num_of_records"`
}

var bot *linebot.Client
var airbox_json airbox
var	client=redis.NewClient(&redis.Options{
		Addr:"hipposerver.ddns.net:6379",
		Password:"",
		DB:0,
	})

func main() {
	url := "https://data.lass-net.org/data/last-all-airbox.json"
	req, _ := http.NewRequest("GET", url, nil)
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)
	errs := json.Unmarshal(body, &airbox_json)
	if errs != nil {
		fmt.Println(errs)
	}
	pushmessage()
	// fmt.Println(airbox_json)
	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 pushmessage(){
	_,err:=bot.PushMessage("U3617adbdd46283d7e859f36302f4f471", linebot.NewTextMessage("hi!")).Do()
	if err!=nil{
		panic(err)
	}
}
func callbackHandler(w http.ResponseWriter, r *http.Request) {
	// t:=time.Now()
	// _, min, _:=t.Clock()
	// if min==0{
	// 	pushmessage()
	// }
	// 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:
				var txtmessage string
				inText := strings.ToLower(message.Text)
				if strings.Contains(inText,"訂閱"){
					userID:=event.Source.UserID
					// pong, _ := client.Ping().Result()
					// txtmessage=pong
					for i:=0; i<len(airbox_json.Feeds); i++ {
						if strings.Contains(inText,strings.ToLower(airbox_json.Feeds[i].Device_id)) {
							val, err:=client.Get(airbox_json.Feeds[i].Device_id).Result()
							if err!=nil{
								client.Set(airbox_json.Feeds[i].Device_id,userID,0)
								txtmessage="訂閱成功!"
								break
							}
							stringSlice:=strings.Split(val,",")
							if stringInSlice(userID,stringSlice){
								txtmessage="您已訂閱過此ID!"
								break
							} else{
								val=val+","+userID
								client.Set(airbox_json.Feeds[i].Device_id,val,0)
								txtmessage="訂閱成功!"
								break
							}
						}
					}
				} else{
					for i:=0; i<len(airbox_json.Feeds); i++ {
						if strings.Contains(inText,strings.ToLower(airbox_json.Feeds[i].Device_id)) {
							txtmessage="Device_id: "+airbox_json.Feeds[i].Device_id+"\n"
							txtmessage=txtmessage+"Site Name: "+airbox_json.Feeds[i].SiteName+"\n"
							txtmessage=txtmessage+"Location: ("+strconv.FormatFloat(float64(airbox_json.Feeds[i].Gps_lon),'f',3,64)+","+strconv.FormatFloat(float64(airbox_json.Feeds[i].Gps_lat),'f',3,64)+")"+"\n"
							txtmessage=txtmessage+"Timestamp: "+airbox_json.Feeds[i].Timestamp+"\n"
							txtmessage=txtmessage+"PM2.5: "+strconv.FormatFloat(float64(airbox_json.Feeds[i].S_d0),'f',0,64)+"\n"
							txtmessage=txtmessage+"Humidity: "+strconv.FormatFloat(float64(airbox_json.Feeds[i].S_h0),'f',0,64)+"\n"
							txtmessage=txtmessage+"Temperature: "+strconv.FormatFloat(float64(airbox_json.Feeds[i].S_t0),'f',0,64)
							break
						}
					}
				}
				if len(txtmessage)==0{
					txtmessage="Sorry! No this device ID, please check again."
				}
				if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(txtmessage)).Do(); err != nil {
					log.Print(err)
				}
			}
		}
	}
}

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/coreos/etcd/client"
	"github.com/gin-gonic/gin"
	"golang.org/x/net/context"
)

func apps(keysAPI client.KeysAPI, username string) ([]string, error) {
	resp, err := keysAPI.Get(context.Background(), "/paus/users/"+username+"/", &client.GetOptions{Sort: true})

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, node := range resp.Node.Nodes {
		appName := strings.Replace(node.Key, "/paus/users/"+username+"/", "", 1)
		result = append(result, appName)
	}

	return result, nil
}

func appURL(uriScheme, identifier, baseDomain string) string {
	return uriScheme + "://" + identifier + "." + baseDomain
}

func appURLs(keysAPI client.KeysAPI, uriScheme, baseDomain, username, appName string) ([]string, error) {
	resp, err := keysAPI.Get(context.Background(), "/paus/users/"+username+"/"+appName+"/revisions/", &client.GetOptions{Sort: true})

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, node := range resp.Node.Nodes {
		revision := strings.Replace(node.Key, "/paus/users/"+username+"/"+appName+"/revisions/", "", 1)
		identifier := username + "-" + appName + "-" + revision
		result = append(result, appURL(uriScheme, identifier, baseDomain))
	}

	return result, nil
}

func latestAppURL(uriScheme, baseDomain, username, appName string) string {
	return uriScheme + "://" + username + "-" + appName + "." + baseDomain
}

func main() {
	baseDomain := os.Getenv("BASE_DOMAIN")
	etcdEndpoint := os.Getenv("ETCD_ENDPOINT")
	uriScheme := os.Getenv("URI_SCHEME")

	if uriScheme == "" {
		uriScheme = "http"
	}

	config := client.Config{
		Endpoints:               []string{etcdEndpoint},
		Transport:               client.DefaultTransport,
		HeaderTimeoutPerRequest: time.Second,
	}

	c, err := client.New(config)

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

	keysAPI := client.NewKeysAPI(c)

	r := gin.Default()
	r.LoadHTMLGlob("templates/*")

	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"alert":   false,
			"error":   false,
			"message": "",
		})
	})

	r.GET("/users/:username", func(c *gin.Context) {
		username := c.Param("username")
		apps, err := apps(keysAPI, username)

		if err != nil {
			c.HTML(http.StatusInternalServerError, "user.tmpl", gin.H{
				"error":   true,
				"message": strings.Join([]string{"error: ", err.Error()}, ""),
			})
		} else {
			c.HTML(http.StatusOK, "user.tmpl", gin.H{
				"error": false,
				"user":  username,
				"apps":  apps,
			})
		}
	})

	r.GET("/users/:username/:appName", func(c *gin.Context) {
		appName := c.Param("appName")
		username := c.Param("username")
		urls, err := appURLs(keysAPI, uriScheme, baseDomain, username, appName)

		if err != nil {
			c.HTML(http.StatusInternalServerError, "app.tmpl", gin.H{
				"error":   true,
				"message": strings.Join([]string{"error: ", err.Error()}, ""),
			})
		} else {
			latestURL := latestAppURL(uriScheme, baseDomain, username, appName)

			c.HTML(http.StatusOK, "app.tmpl", gin.H{
				"error":     false,
				"user":      username,
				"app":       appName,
				"latestURL": latestURL,
				"urls":      urls,
			})
		}
	})

	r.POST("/submit", func(c *gin.Context) {
		username := c.PostForm("username")
		pubKey := c.PostForm("pubKey")

		// libcompose does not support `docker-compose run`...
		out, err := exec.Command("docker-compose", "-p", "paus", "run", "--rm", "gitreceive-upload-key", username, pubKey).Output()

		if err != nil {
			c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
				"alert":   true,
				"error":   true,
				"message": strings.Join([]string{"error: ", err.Error()}, ""),
			})
		} else {
			c.HTML(http.StatusCreated, "index.tmpl", gin.H{
				"alert":   true,
				"error":   false,
				"message": strings.Join([]string{"fingerprint: ", string(out)}, ""),
			})
		}
	})

	r.Run()
}
<commit_msg>Rename lastAppURL to lastAppURLOfUser<commit_after>package main

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/coreos/etcd/client"
	"github.com/gin-gonic/gin"
	"golang.org/x/net/context"
)

func apps(keysAPI client.KeysAPI, username string) ([]string, error) {
	resp, err := keysAPI.Get(context.Background(), "/paus/users/"+username+"/", &client.GetOptions{Sort: true})

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, node := range resp.Node.Nodes {
		appName := strings.Replace(node.Key, "/paus/users/"+username+"/", "", 1)
		result = append(result, appName)
	}

	return result, nil
}

func appURL(uriScheme, identifier, baseDomain string) string {
	return uriScheme + "://" + identifier + "." + baseDomain
}

func appURLs(keysAPI client.KeysAPI, uriScheme, baseDomain, username, appName string) ([]string, error) {
	resp, err := keysAPI.Get(context.Background(), "/paus/users/"+username+"/"+appName+"/revisions/", &client.GetOptions{Sort: true})

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, node := range resp.Node.Nodes {
		revision := strings.Replace(node.Key, "/paus/users/"+username+"/"+appName+"/revisions/", "", 1)
		identifier := username + "-" + appName + "-" + revision
		result = append(result, appURL(uriScheme, identifier, baseDomain))
	}

	return result, nil
}

func latestAppURLOfUser(uriScheme, baseDomain, username, appName string) string {
	identifier := username + "-" + appName
	return appURL(uriScheme, identifier, baseDomain)
}

func main() {
	baseDomain := os.Getenv("BASE_DOMAIN")
	etcdEndpoint := os.Getenv("ETCD_ENDPOINT")
	uriScheme := os.Getenv("URI_SCHEME")

	if uriScheme == "" {
		uriScheme = "http"
	}

	config := client.Config{
		Endpoints:               []string{etcdEndpoint},
		Transport:               client.DefaultTransport,
		HeaderTimeoutPerRequest: time.Second,
	}

	c, err := client.New(config)

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

	keysAPI := client.NewKeysAPI(c)

	r := gin.Default()
	r.LoadHTMLGlob("templates/*")

	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"alert":   false,
			"error":   false,
			"message": "",
		})
	})

	r.GET("/users/:username", func(c *gin.Context) {
		username := c.Param("username")
		apps, err := apps(keysAPI, username)

		if err != nil {
			c.HTML(http.StatusInternalServerError, "user.tmpl", gin.H{
				"error":   true,
				"message": strings.Join([]string{"error: ", err.Error()}, ""),
			})
		} else {
			c.HTML(http.StatusOK, "user.tmpl", gin.H{
				"error": false,
				"user":  username,
				"apps":  apps,
			})
		}
	})

	r.GET("/users/:username/:appName", func(c *gin.Context) {
		appName := c.Param("appName")
		username := c.Param("username")
		urls, err := appURLs(keysAPI, uriScheme, baseDomain, username, appName)

		if err != nil {
			c.HTML(http.StatusInternalServerError, "app.tmpl", gin.H{
				"error":   true,
				"message": strings.Join([]string{"error: ", err.Error()}, ""),
			})
		} else {
			latestURL := latestAppURLOfUser(uriScheme, baseDomain, username, appName)

			c.HTML(http.StatusOK, "app.tmpl", gin.H{
				"error":     false,
				"user":      username,
				"app":       appName,
				"latestURL": latestURL,
				"urls":      urls,
			})
		}
	})

	r.POST("/submit", func(c *gin.Context) {
		username := c.PostForm("username")
		pubKey := c.PostForm("pubKey")

		// libcompose does not support `docker-compose run`...
		out, err := exec.Command("docker-compose", "-p", "paus", "run", "--rm", "gitreceive-upload-key", username, pubKey).Output()

		if err != nil {
			c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
				"alert":   true,
				"error":   true,
				"message": strings.Join([]string{"error: ", err.Error()}, ""),
			})
		} else {
			c.HTML(http.StatusCreated, "index.tmpl", gin.H{
				"alert":   true,
				"error":   false,
				"message": strings.Join([]string{"fingerprint: ", string(out)}, ""),
			})
		}
	})

	r.Run()
}
<|endoftext|>


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

// bcrypt-tool is command line tool for common bcrypt functions
// including the ability to generate hashes, determine if a password
// matches a hash, and compute cost from a hash.
package main

import (
	"fmt"
	"os"
	"strconv"

	"code.google.com/p/go.crypto/bcrypt"
)

const (
	helpText = `Usage: bcrypt-tool [action] argument ...
  ACTIONS
    hash  [password] <cost> Generate hash given password and optional cost (4-31)
    match [password] [hash] Print "yes" and return 0 if password is a match
                            for hash, or print "no" and return 1 otherwise
    cost  [hash]            Print the cost of hash (4-31)
`
)

func main() {
	os.Args = os.Args[1:]

	if len(os.Args) < 2 {
		help()
	}
	switch os.Args[0] {
	case "cost":
		if len(os.Args) != 2 {
			help()
		}
		c := cost(os.Args[1])
		fmt.Println(fmt.Sprintf("%d", c))
	case "match":
		if len(os.Args) != 3 {
			help()
		}
		ok := match(os.Args[1], os.Args[2])
		if ok {
			fmt.Println("yes")
		} else {
			fmt.Println("no")
			os.Exit(1)
		}
	case "hash":
		if len(os.Args) > 4 {
			help()
		}
		passwd := os.Args[1]
		cost := bcrypt.DefaultCost
		if len(os.Args) == 3 {
			c, e := strconv.Atoi(os.Args[2])
			if e != nil {
				help()
			}
			cost = c
		}
		hash := hash(passwd, cost)
		fmt.Println(hash)
	default:
		help()
	}
}

func help() {
	fmt.Fprintln(os.Stderr, helpText)
	os.Exit(2)
}

func cost(hash string) int {
	h := []byte(hash)
	c, e := bcrypt.Cost(h)
	if e != nil {
		fmt.Fprintln(os.Stderr, e)
		os.Exit(2)
	}
	return c
}

func match(password, hash string) bool {
	p := []byte(password)
	h := []byte(hash)
	e := bcrypt.CompareHashAndPassword(h, p)
	if e != nil {
		return false
	}
	return true
}

func hash(password string, cost int) string {
	p := []byte(password)
	h, e := bcrypt.GenerateFromPassword(p, cost)
	if e != nil {
		fmt.Fprintln(os.Stderr, e)
		os.Exit(2)
	}
	return string(h)
}
<commit_msg>Update bcrypt import<commit_after>// Copyright 2014 Seth Hoenig. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// bcrypt-tool is command line tool for common bcrypt functions
// including the ability to generate hashes, determine if a password
// matches a hash, and compute cost from a hash.
package main

import (
	"fmt"
	"os"
	"strconv"

	"golang.org/x/crypto/bcrypt"
)

const (
	helpText = `Usage: bcrypt-tool [action] argument ...
  ACTIONS
    hash  [password] <cost> Generate hash given password and optional cost (4-31)
    match [password] [hash] Print "yes" and return 0 if password is a match
                            for hash, or print "no" and return 1 otherwise
    cost  [hash]            Print the cost of hash (4-31)
`
)

func main() {
	os.Args = os.Args[1:]

	if len(os.Args) < 2 {
		help()
	}
	switch os.Args[0] {
	case "cost":
		if len(os.Args) != 2 {
			help()
		}
		c := cost(os.Args[1])
		fmt.Println(fmt.Sprintf("%d", c))
	case "match":
		if len(os.Args) != 3 {
			help()
		}
		ok := match(os.Args[1], os.Args[2])
		if ok {
			fmt.Println("yes")
		} else {
			fmt.Println("no")
			os.Exit(1)
		}
	case "hash":
		if len(os.Args) > 4 {
			help()
		}
		passwd := os.Args[1]
		cost := bcrypt.DefaultCost
		if len(os.Args) == 3 {
			c, e := strconv.Atoi(os.Args[2])
			if e != nil {
				help()
			}
			cost = c
		}
		hash := hash(passwd, cost)
		fmt.Println(hash)
	default:
		help()
	}
}

func help() {
	fmt.Fprintln(os.Stderr, helpText)
	os.Exit(2)
}

func cost(hash string) int {
	h := []byte(hash)
	c, e := bcrypt.Cost(h)
	if e != nil {
		fmt.Fprintln(os.Stderr, e)
		os.Exit(2)
	}
	return c
}

func match(password, hash string) bool {
	p := []byte(password)
	h := []byte(hash)
	e := bcrypt.CompareHashAndPassword(h, p)
	if e != nil {
		return false
	}
	return true
}

func hash(password string, cost int) string {
	p := []byte(password)
	h, e := bcrypt.GenerateFromPassword(p, cost)
	if e != nil {
		fmt.Fprintln(os.Stderr, e)
		os.Exit(2)
	}
	return string(h)
}
<|endoftext|>


<commit_before>package main

import "fmt"

import "github.com/jessevdk/go-flags"
import "github.com/tj/go-debug"
import "github.com/peterh/liner"
import "github.com/aws/aws-sdk-go/aws/credentials"
import "time"

const VERSION = "0.6.1"

func main() {
	var opts struct {
		ConfigFile   string `short:"c" long:"config" description:"Path to config file"`
		PrintVersion bool   `short:"v" long:"version" description:"Print version number and exit"`
	}

	debug := debug.Debug("oktad:main")
	args, err := flags.Parse(&opts)

	if err != nil {
		fmt.Println(err)
		return
	}

	if opts.PrintVersion {
		fmt.Printf("oktad v%s\n", VERSION)
		return
	}

	debug("loading configuration data")
	// try to load configuration
	oktaCfg, err := parseConfig(opts.ConfigFile)

	if err != nil {
		fmt.Println("Error reading config file!")
		debug("cfg read err: %s", err)
		return
	}

	if len(args) <= 0 {
		fmt.Println("Hey, that command won't actually do anything.\n\nSorry.")
		return
	}

	awsProfile := args[0]
	acfg, err := readAwsProfile(
		fmt.Sprintf("profile %s", awsProfile),
	)

	var skipSecondRole bool

	if err != nil {
		//fmt.Println("Error reading your AWS profile!")
		debug("error reading AWS profile: %s", err)
		if err == awsProfileNotFound {
			// if the AWS profile isn't found, we'll assume that
			// the user intends to run a command in the first account
			// behind their okta auth, rather than assuming role twice
			skipSecondRole = true
			fmt.Printf(
				"We couldn't find an AWS profile named %s,\nso we will AssumeRole into your base account.\n",
				awsProfile,
			)
			awsProfile = BASE_PROFILE_CREDS

			args = append([]string{BASE_PROFILE_CREDS}, args...)
		}
	}

	maybeCreds, err := loadCreds(awsProfile)
	if err == nil {
		debug("found cached credentials, going to use them")
		// if we could load creds, use them!
		err := prepAndLaunch(args, maybeCreds)
		if err != nil {
			fmt.Println("Error launching program: ", err)
		}
		return
	}

	debug("cred load err %s", err)

	user, pass, err := readUserPass()
	if err != nil {
		// if we got an error here, the user bailed on us
		debug("control-c caught in liner, probably")
		return
	}

	if user == "" || pass == "" {
		fmt.Println("Must supply a username and password!")
		return
	}

	ores, err := login(oktaCfg, user, pass)
	if err != nil {
		fmt.Println("Error authenticating with Okta! Maybe your username or password are wrong.")
		debug("login err %s", err)
		return
	}

	if ores.Status != "MFA_REQUIRED" {
		fmt.Println("MFA required to use this tool.")
		return
	}

	factor, err := extractTokenFactor(ores)

	if err != nil {
		fmt.Println("Error processing okta response!")
		debug("err from extractTokenFactor was %s", err)
		return
	}

	mfaToken, err := readMfaToken()
	if err != nil {
		debug("control-c caught in liner, probably")
		return
	}

	sessionToken, err := doMfa(ores, factor, mfaToken)
	if err != nil {
		fmt.Println("Error performing MFA auth!")
		debug("error from doMfa was %s", err)
		return
	}

	saml, err := getSaml(oktaCfg, sessionToken)
	debug("got saml: \n%s", saml.raw)

	if err != nil {
		fmt.Println("Error preparing to AssumeRole!")
		debug("getSaml err was %s", err)
		return
	}

	mainCreds, mExp, err := assumeFirstRole(acfg, saml)
	if err != nil {
		fmt.Println("Error assuming first role!")
		debug("error was %s", err)
		return
	}

	var finalCreds *credentials.Credentials
	var fExp time.Time
	if !skipSecondRole {
		finalCreds, fExp, err = assumeDestinationRole(acfg, mainCreds)
		if err != nil {
			fmt.Println("Error assuming second role!")
			debug("error was %s", err)
			return
		}
	} else {
		finalCreds = mainCreds
		fExp = mExp
	}

	// all was good, so let's save credentials...
	err = storeCreds(awsProfile, finalCreds, fExp)
	if err != nil {
		debug("err storing credentials, %s", err)
	}

	fmt.Println("Everything looks good; launching your program...")
	err = prepAndLaunch(args, finalCreds)
	if err != nil {
		fmt.Println("Error launching program: ", err)
	}
}

// reads the username and password from the command line
// returns user, then pass, then an error
func readUserPass() (user string, pass string, err error) {
	li := liner.NewLiner()

	// remember to close or weird stuff happens
	defer li.Close()

	li.SetCtrlCAborts(true)
	user, err = li.Prompt("Username: ")
	if err != nil {
		return
	}

	pass, err = li.PasswordPrompt("Password: ")
	if err != nil {
		return
	}

	return
}

// reads and returns an mfa token
func readMfaToken() (string, error) {
	li := liner.NewLiner()
	defer li.Close()
	li.SetCtrlCAborts(true)
	fmt.Println("Your account requires MFA; please enter a token.")
	return li.Prompt("MFA token: ")
}
<commit_msg>increase version to 0.6.2<commit_after>package main

import "fmt"

import "github.com/jessevdk/go-flags"
import "github.com/tj/go-debug"
import "github.com/peterh/liner"
import "github.com/aws/aws-sdk-go/aws/credentials"
import "time"

const VERSION = "0.6.2"

func main() {
	var opts struct {
		ConfigFile   string `short:"c" long:"config" description:"Path to config file"`
		PrintVersion bool   `short:"v" long:"version" description:"Print version number and exit"`
	}

	debug := debug.Debug("oktad:main")
	args, err := flags.Parse(&opts)

	if err != nil {
		fmt.Println(err)
		return
	}

	if opts.PrintVersion {
		fmt.Printf("oktad v%s\n", VERSION)
		return
	}

	debug("loading configuration data")
	// try to load configuration
	oktaCfg, err := parseConfig(opts.ConfigFile)

	if err != nil {
		fmt.Println("Error reading config file!")
		debug("cfg read err: %s", err)
		return
	}

	if len(args) <= 0 {
		fmt.Println("Hey, that command won't actually do anything.\n\nSorry.")
		return
	}

	awsProfile := args[0]
	acfg, err := readAwsProfile(
		fmt.Sprintf("profile %s", awsProfile),
	)

	var skipSecondRole bool

	if err != nil {
		//fmt.Println("Error reading your AWS profile!")
		debug("error reading AWS profile: %s", err)
		if err == awsProfileNotFound {
			// if the AWS profile isn't found, we'll assume that
			// the user intends to run a command in the first account
			// behind their okta auth, rather than assuming role twice
			skipSecondRole = true
			fmt.Printf(
				"We couldn't find an AWS profile named %s,\nso we will AssumeRole into your base account.\n",
				awsProfile,
			)
			awsProfile = BASE_PROFILE_CREDS

			args = append([]string{BASE_PROFILE_CREDS}, args...)
		}
	}

	maybeCreds, err := loadCreds(awsProfile)
	if err == nil {
		debug("found cached credentials, going to use them")
		// if we could load creds, use them!
		err := prepAndLaunch(args, maybeCreds)
		if err != nil {
			fmt.Println("Error launching program: ", err)
		}
		return
	}

	debug("cred load err %s", err)

	user, pass, err := readUserPass()
	if err != nil {
		// if we got an error here, the user bailed on us
		debug("control-c caught in liner, probably")
		return
	}

	if user == "" || pass == "" {
		fmt.Println("Must supply a username and password!")
		return
	}

	ores, err := login(oktaCfg, user, pass)
	if err != nil {
		fmt.Println("Error authenticating with Okta! Maybe your username or password are wrong.")
		debug("login err %s", err)
		return
	}

	if ores.Status != "MFA_REQUIRED" {
		fmt.Println("MFA required to use this tool.")
		return
	}

	factor, err := extractTokenFactor(ores)

	if err != nil {
		fmt.Println("Error processing okta response!")
		debug("err from extractTokenFactor was %s", err)
		return
	}

	mfaToken, err := readMfaToken()
	if err != nil {
		debug("control-c caught in liner, probably")
		return
	}

	sessionToken, err := doMfa(ores, factor, mfaToken)
	if err != nil {
		fmt.Println("Error performing MFA auth!")
		debug("error from doMfa was %s", err)
		return
	}

	saml, err := getSaml(oktaCfg, sessionToken)
	debug("got saml: \n%s", saml.raw)

	if err != nil {
		fmt.Println("Error preparing to AssumeRole!")
		debug("getSaml err was %s", err)
		return
	}

	mainCreds, mExp, err := assumeFirstRole(acfg, saml)
	if err != nil {
		fmt.Println("Error assuming first role!")
		debug("error was %s", err)
		return
	}

	var finalCreds *credentials.Credentials
	var fExp time.Time
	if !skipSecondRole {
		finalCreds, fExp, err = assumeDestinationRole(acfg, mainCreds)
		if err != nil {
			fmt.Println("Error assuming second role!")
			debug("error was %s", err)
			return
		}
	} else {
		finalCreds = mainCreds
		fExp = mExp
	}

	// all was good, so let's save credentials...
	err = storeCreds(awsProfile, finalCreds, fExp)
	if err != nil {
		debug("err storing credentials, %s", err)
	}

	fmt.Println("Everything looks good; launching your program...")
	err = prepAndLaunch(args, finalCreds)
	if err != nil {
		fmt.Println("Error launching program: ", err)
	}
}

// reads the username and password from the command line
// returns user, then pass, then an error
func readUserPass() (user string, pass string, err error) {
	li := liner.NewLiner()

	// remember to close or weird stuff happens
	defer li.Close()

	li.SetCtrlCAborts(true)
	user, err = li.Prompt("Username: ")
	if err != nil {
		return
	}

	pass, err = li.PasswordPrompt("Password: ")
	if err != nil {
		return
	}

	return
}

// reads and returns an mfa token
func readMfaToken() (string, error) {
	li := liner.NewLiner()
	defer li.Close()
	li.SetCtrlCAborts(true)
	fmt.Println("Your account requires MFA; please enter a token.")
	return li.Prompt("MFA token: ")
}
<|endoftext|>