<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"

	"github.com/surma/httptools"
	"github.com/voxelbrain/goptions"

	"github.com/TrevorSStone/goriot"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

var (
	options = struct {
		Port              int           `goptions:"-p, --port, description='Port to bind webserver to'"`
		MongoDB           string        `goptions:"-m, --mongodb, description='URL of MongoDB', obligatory"`
		APIKey            string        `goptions:"-k, --key, description='Riot API key', obligatory"`
		StaticContent     string        `goptions:"--static, description='Path to static content folder'"`
		SummonerWhitelist string        `goptions:"-w, --whitelist, description='List of whitelisted summoner IDs separated by colon'"`
		Help              goptions.Help `goptions:"-h, --help, description='Show this help'"`
	}{
		Port:          5000,
		StaticContent: "dist",
	}
)

var (
	db *mgo.Database
)

func main() {
	goptions.ParseAndFail(&options)

	goriot.SetAPIKey(options.APIKey)

	session, err := mgo.Dial(options.MongoDB)
	if err != nil {
		log.Fatalf("Could not connect to MongoDB: %s", err)
	}
	db = session.DB("")

	r := httptools.NewRegexpSwitch(map[string]http.Handler{
		"/([a-z]+)/([0-9]+)/parse": httptools.L{
			httptools.SilentHandler(http.HandlerFunc(whitelistHandler)),
			httptools.L{
				httptools.SilentHandler(http.HandlerFunc(parseMatchHistory)),
				http.HandlerFunc(dumpMatchHistory),
			},
		},
		"/([a-z]+)/([0-9]+)": httptools.L{
			httptools.SilentHandler(http.HandlerFunc(whitelistHandler)),
			httptools.MethodSwitch{
				"POST": httptools.L{
					httptools.SilentHandler(http.HandlerFunc(parseMatchHistory)),
					http.HandlerFunc(saveMatchHistory),
				},
				"GET": httptools.L{
					httptools.SilentHandler(http.HandlerFunc(queryMatchHistory)),
					http.HandlerFunc(dumpMatchHistory),
				},
			},
		},
		"/.*": http.FileServer(http.Dir(options.StaticContent)),
	})

	addr := fmt.Sprintf("0.0.0.0:%d", options.Port)
	log.Printf("Starting webserver on %s...", addr)
	if err := http.ListenAndServe(addr, r); err != nil {
		log.Fatalf("Could not start webserver: %s", err)
	}
}

var (
	SERVERS = []string{"br", "eune", "euw", "lan", "las", "na", "oce"}
)

func whitelistHandler(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	server, summonerId := vars["1"].(string), vars["2"].(string)
	server = strings.ToLower(server)

	if !StringArray(SERVERS).Contains(server) {
		http.Error(w, "Invalid region", http.StatusBadRequest)
		return
	}
	vars["server"] = server

	numSummonerId, err := strconv.ParseInt(summonerId, 10, 64)
	if err != nil {
		http.Error(w, "Non-numeric summoner id", http.StatusBadRequest)
		return
	}
	vars["summonerId"] = numSummonerId

	if !StringArray(strings.Split(options.SummonerWhitelist, ":")).Contains(server + "/" + summonerId) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
}

func parseMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	server, summonerId := vars["server"].(string), vars["summonerId"].(int64)

	mh, err := goriot.RecentGameBySummoner(server, summonerId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	vars["history"] = mh
}

func saveMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	mh := vars["history"].([]goriot.Game)
	server, summonerId := vars["server"].(string), vars["summonerId"].(int64)
	c := db.C(fmt.Sprintf("%s-%d", server, summonerId))

	for _, m := range mh {
		_, err := c.Upsert(bson.M{
			"timestamp": m.CreateDate,
		}, m)
		if err != nil {
			log.Printf("Update failed: %s", err)
			http.Error(w, "Update failed", http.StatusInternalServerError)
			return
		}
	}
	http.Error(w, "", http.StatusNoContent)
}

func dumpMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()

	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	enc.Encode(vars["history"])
}

func queryMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	server, summonerId := vars["server"].(string), vars["summonerId"].(int64)
	c := db.C(fmt.Sprintf("%s-%d", server, summonerId))

	var mh []Game
	if err := c.Find(bson.M{}).Sort("-createDate").All(&mh); err != nil {
		log.Printf("Query failed: %s", err)
		http.Error(w, "Query failed", http.StatusInternalServerError)
		return
	}

	vars["history"] = mh
}

type StringArray []string

func (sa StringArray) Contains(s string) bool {
	for _, v := range sa {
		if v == s {
			return true
		}
	}
	return false
}
<commit_msg>Fix uniqueness issue<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"

	"github.com/surma/httptools"
	"github.com/voxelbrain/goptions"

	"github.com/TrevorSStone/goriot"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

var (
	options = struct {
		Port              int           `goptions:"-p, --port, description='Port to bind webserver to'"`
		MongoDB           string        `goptions:"-m, --mongodb, description='URL of MongoDB', obligatory"`
		APIKey            string        `goptions:"-k, --key, description='Riot API key', obligatory"`
		StaticContent     string        `goptions:"--static, description='Path to static content folder'"`
		SummonerWhitelist string        `goptions:"-w, --whitelist, description='List of whitelisted summoner IDs separated by colon'"`
		Help              goptions.Help `goptions:"-h, --help, description='Show this help'"`
	}{
		Port:          5000,
		StaticContent: "dist",
	}
)

var (
	db *mgo.Database
)

func init() {
	goriot.BaseURL = "http://euw.api.pvp.net/api"
}

func main() {
	goptions.ParseAndFail(&options)

	goriot.SetAPIKey(options.APIKey)

	session, err := mgo.Dial(options.MongoDB)
	if err != nil {
		log.Fatalf("Could not connect to MongoDB: %s", err)
	}
	db = session.DB("")

	r := httptools.NewRegexpSwitch(map[string]http.Handler{
		"/([a-z]+)/([0-9]+)/parse": httptools.L{
			httptools.SilentHandler(http.HandlerFunc(whitelistHandler)),
			httptools.L{
				httptools.SilentHandler(http.HandlerFunc(parseMatchHistory)),
				http.HandlerFunc(dumpMatchHistory),
			},
		},
		"/([a-z]+)/([0-9]+)": httptools.L{
			httptools.SilentHandler(http.HandlerFunc(whitelistHandler)),
			httptools.MethodSwitch{
				"POST": httptools.L{
					httptools.SilentHandler(http.HandlerFunc(parseMatchHistory)),
					http.HandlerFunc(saveMatchHistory),
				},
				"GET": httptools.L{
					httptools.SilentHandler(http.HandlerFunc(queryMatchHistory)),
					http.HandlerFunc(dumpMatchHistory),
				},
			},
		},
		"/.*": http.FileServer(http.Dir(options.StaticContent)),
	})

	addr := fmt.Sprintf("0.0.0.0:%d", options.Port)
	log.Printf("Starting webserver on %s...", addr)
	if err := http.ListenAndServe(addr, r); err != nil {
		log.Fatalf("Could not start webserver: %s", err)
	}
}

var (
	SERVERS = []string{"br", "eune", "euw", "lan", "las", "na", "oce"}
)

func whitelistHandler(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	server, summonerId := vars["1"].(string), vars["2"].(string)
	server = strings.ToLower(server)

	if !StringArray(SERVERS).Contains(server) {
		http.Error(w, "Invalid region", http.StatusBadRequest)
		return
	}
	vars["server"] = server

	numSummonerId, err := strconv.ParseInt(summonerId, 10, 64)
	if err != nil {
		http.Error(w, "Non-numeric summoner id", http.StatusBadRequest)
		return
	}
	vars["summonerId"] = numSummonerId

	if !StringArray(strings.Split(options.SummonerWhitelist, ":")).Contains(server + "/" + summonerId) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}
}

func parseMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	server, summonerId := vars["server"].(string), vars["summonerId"].(int64)

	mh, err := goriot.RecentGameBySummoner(server, summonerId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	vars["history"] = mh
}

func saveMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	mh := vars["history"].([]goriot.Game)
	server, summonerId := vars["server"].(string), vars["summonerId"].(int64)
	c := db.C(fmt.Sprintf("%s-%d", server, summonerId))

	for _, m := range mh {
		_, err := c.Upsert(bson.M{
			"createdate": m.CreateDate,
		}, m)
		if err != nil {
			log.Printf("Update failed: %s", err)
			http.Error(w, "Update failed", http.StatusInternalServerError)
			return
		}
	}
	http.Error(w, "", http.StatusNoContent)
}

func dumpMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()

	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)
	enc.Encode(vars["history"])
}

func queryMatchHistory(w http.ResponseWriter, r *http.Request) {
	vars := w.(httptools.VarsResponseWriter).Vars()
	server, summonerId := vars["server"].(string), vars["summonerId"].(int64)
	c := db.C(fmt.Sprintf("%s-%d", server, summonerId))

	var mh []Game
	if err := c.Find(bson.M{}).Sort("-createdate").All(&mh); err != nil {
		log.Printf("Query failed: %s", err)
		http.Error(w, "Query failed", http.StatusInternalServerError)
		return
	}

	vars["history"] = mh
}

type StringArray []string

func (sa StringArray) Contains(s string) bool {
	for _, v := range sa {
		if v == s {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"runtime"
	"strings"

	. "gist.github.com/7480523.git"
	. "gist.github.com/7651991.git"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	reduceFunc := func(in string) interface{} {
		if x := SomethingFromImportPath(in); x != nil {
			Standard := x.Bpkg.Goroot && x.Bpkg.ImportPath != "" && !strings.Contains(x.Bpkg.ImportPath, ".")

			if !Standard {
				x.Update()
				return x.String()
			}
		}
		return nil
	}

	outChan := GoReduceLinesFromReader(os.Stdin, 8, reduceFunc)

	for out := range outChan {
		fmt.Println(out.(string))
	}
}
<commit_msg>Skip doing remote work for repeated git repos.<commit_after>package main

import (
	"fmt"
	"os"
	"runtime"
	"strings"
	"sync"

	. "gist.github.com/7480523.git"
	. "gist.github.com/7651991.git"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	var lock sync.Mutex
	checkedGitRepos := map[string]bool{}

	reduceFunc := func(in string) interface{} {
		if x := SomethingFromImportPath(in); x != nil {
			Standard := x.Bpkg.Goroot && x.Bpkg.ImportPath != "" && !strings.Contains(x.Bpkg.ImportPath, ".")

			if !Standard {
				// HACK: Check that the same git repo hasn't already been done
				if isGitRepo, rootPath := GetGitRepoRoot(x.Path); isGitRepo {
					lock.Lock()
					if !checkedGitRepos[rootPath] {
						checkedGitRepos[rootPath] = true
						lock.Unlock()
					} else {
						lock.Unlock()
						// TODO: Instead of skipping git repos that were done, cache their state and reuse it
						return "@---- " + x.Bpkg.ImportPath
					}
				}

				x.Update()
				return x.String()
			}
		}
		return nil
	}

	outChan := GoReduceLinesFromReader(os.Stdin, 8, reduceFunc)

	for out := range outChan {
		fmt.Println(out.(string))
	}
}
<|endoftext|>


<commit_before>package main

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

func ProxyServer(w http.ResponseWriter, req *http.Request) {
	for k, v := range req.Header {
		fmt.Printf("%s - %s\n", k, strings.Join(v, ","))
	}

	fmt.Fprintf(w, "hello, world!\n")
}

func main() {
	http.HandleFunc("/", ProxyServer)
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Print ok<commit_after>package main

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

func ProxyServer(w http.ResponseWriter, req *http.Request) {
	for k, v := range req.Header {
		fmt.Printf("%s - %s\n", k, strings.Join(v, ","))
	}

	fmt.Fprintln(w, "ok")
}

func main() {
	http.HandleFunc("/", ProxyServer)
	err := http.ListenAndServe(":12345", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
    "github.com/AntonioLangiu/hknbot/common"
    "github.com/AntonioLangiu/hknbot/bot"
)

func main() {
    configuration := common.LoadConfiguration()
    go common.WebServer()
    bot.LoadBot(configuration)
}
<commit_msg>check format<commit_after>package main

import (
	"github.com/AntonioLangiu/hknbot/bot"
	"github.com/AntonioLangiu/hknbot/common"
)

func main() {
	configuration := common.LoadConfiguration()
	go common.WebServer()
	bot.LoadBot(configuration)
}
<|endoftext|>


<commit_before>package vault

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/cloudfoundry-community/vaultkv"
	"github.com/jhunt/go-ansi"
	"github.com/starkandwayne/safe/prompt"
	"golang.org/x/crypto/ssh/terminal"
)

var termState *terminal.State

func (v *Vault) cancelRekey() {
	if termState != nil {
		terminal.Restore(int(os.Stdin.Fd()), termState)
	}
	err := v.client.RekeyCancel()
	if err != nil {
		ansi.Fprintf(os.Stderr, "Failed to cancel rekey process: %s\n", err.Error())
		return
	}

	ansi.Fprintf(os.Stderr, "@y{Vault rekey canceled successfully}\n")
}

func (v *Vault) ReKey(unsealKeyCount, numToUnseal int, pgpKeys []string) ([]string, error) {
	err := v.client.RekeyCancel()
	if err != nil {
		return nil, fmt.Errorf("An error occurred when trying to cancel potentially preexisting rekey: %s", err)
	}

	backup := len(pgpKeys) > 0
	rekey, err := v.client.NewRekey(vaultkv.RekeyConfig{
		Shares:    unsealKeyCount,
		Threshold: numToUnseal,
		PGPKeys:   pgpKeys,
		Backup:    backup,
	})
	if err != nil {
		return nil, fmt.Errorf("An error occurred when starting a new rekey operation: %s", err)
	}

	// we successfully started a rekey, we should now cancel on failure, unless we finish rekeying
	var shouldCancelRekey = true
	defer func() {
		if shouldCancelRekey {
			v.cancelRekey()
		}
	}()
	sighandler := make(chan os.Signal, 4)
	signal.Ignore(os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	signal.Notify(sighandler, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		for _ = range sighandler {
			v.cancelRekey()
			os.Exit(1)
		}
	}()

	if terminal.IsTerminal(int(os.Stdin.Fd())) {
		termState, err = terminal.GetState(int(os.Stdin.Fd()))
		if err != nil {
			return nil, err
		}
	}

	givenKeys := make([]string, rekey.Remaining())

	for i := 0; i < len(givenKeys); i++ {
		givenKeys[i] = prompt.Secure("Unseal Key %d: ", rekey.State().Progress+1)
	}

	rekeyDone, err := rekey.Submit(givenKeys...)
	if err != nil {
		return nil, fmt.Errorf("Key submission failed: %s", err)
	}
	if !rekeyDone {
		return nil, fmt.Errorf("The rekey did not finish (is somebody else trying to rekey at the same time?)")
	}

	// vault should be rekeyed by here, as our progress met the requirement
	shouldCancelRekey = false
	signal.Stop(sighandler)

	return rekey.Keys(), nil
}
<commit_msg>Rekey reports key number correctly<commit_after>package vault

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/cloudfoundry-community/vaultkv"
	"github.com/jhunt/go-ansi"
	"github.com/starkandwayne/safe/prompt"
	"golang.org/x/crypto/ssh/terminal"
)

var termState *terminal.State

func (v *Vault) cancelRekey() {
	if termState != nil {
		terminal.Restore(int(os.Stdin.Fd()), termState)
	}
	err := v.client.RekeyCancel()
	if err != nil {
		ansi.Fprintf(os.Stderr, "Failed to cancel rekey process: %s\n", err.Error())
		return
	}

	ansi.Fprintf(os.Stderr, "@y{Vault rekey canceled successfully}\n")
}

func (v *Vault) ReKey(unsealKeyCount, numToUnseal int, pgpKeys []string) ([]string, error) {
	err := v.client.RekeyCancel()
	if err != nil {
		return nil, fmt.Errorf("An error occurred when trying to cancel potentially preexisting rekey: %s", err)
	}

	backup := len(pgpKeys) > 0
	rekey, err := v.client.NewRekey(vaultkv.RekeyConfig{
		Shares:    unsealKeyCount,
		Threshold: numToUnseal,
		PGPKeys:   pgpKeys,
		Backup:    backup,
	})
	if err != nil {
		return nil, fmt.Errorf("An error occurred when starting a new rekey operation: %s", err)
	}

	// we successfully started a rekey, we should now cancel on failure, unless we finish rekeying
	var shouldCancelRekey = true
	defer func() {
		if shouldCancelRekey {
			v.cancelRekey()
		}
	}()
	sighandler := make(chan os.Signal, 4)
	signal.Ignore(os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	signal.Notify(sighandler, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	go func() {
		for _ = range sighandler {
			v.cancelRekey()
			os.Exit(1)
		}
	}()

	if terminal.IsTerminal(int(os.Stdin.Fd())) {
		termState, err = terminal.GetState(int(os.Stdin.Fd()))
		if err != nil {
			return nil, err
		}
	}

	givenKeys := make([]string, rekey.Remaining())

	for i := 0; i < len(givenKeys); i++ {
		givenKeys[i] = prompt.Secure("Unseal Key %d: ", i+1)
	}

	rekeyDone, err := rekey.Submit(givenKeys...)
	if err != nil {
		return nil, fmt.Errorf("Key submission failed: %s", err)
	}
	if !rekeyDone {
		return nil, fmt.Errorf("The rekey did not finish (is somebody else trying to rekey at the same time?)")
	}

	// vault should be rekeyed by here, as our progress met the requirement
	shouldCancelRekey = false
	signal.Stop(sighandler)

	return rekey.Keys(), nil
}
<|endoftext|>


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

package main

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

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

var bot *linebot.Client
var PetDB *Pets

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

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

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

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

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

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

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

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

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

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

package main

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

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

var bot *linebot.Client
var PetDB *Pets

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

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

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

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

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

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

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

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

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

		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/jessevdk/go-flags"
	"github.com/martinp/atbapi/api"
	"github.com/martinp/atbapi/atb"
	"log"
	"os"
)

func main() {
	var opts struct {
		Listen string `short:"l" long:"listen" description:"Listen address" default:":8080"`
		Config string `short:"c" long:"config" description:"Path to config file" value-name:"FILE" default:"config.json"`
	}
	_, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		os.Exit(1)
	}

	client, err := atb.NewFromConfig(opts.Config)
	if err != nil {
		log.Fatal(err)
	}

	if err := api.ListenAndServe(client, opts.Listen); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Log listening address<commit_after>package main

import (
	"github.com/jessevdk/go-flags"
	"github.com/martinp/atbapi/api"
	"github.com/martinp/atbapi/atb"
	"log"
	"os"
)

func main() {
	var opts struct {
		Listen string `short:"l" long:"listen" description:"Listen address" default:":8080"`
		Config string `short:"c" long:"config" description:"Path to config file" value-name:"FILE" default:"config.json"`
	}
	_, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		os.Exit(1)
	}

	client, err := atb.NewFromConfig(opts.Config)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Listening on %s", opts.Listen)
	if err := api.ListenAndServe(client, opts.Listen); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/md5"
	"flag"
	"fmt"
	"github.com/vharitonsky/iniflags"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"strconv"
)

var (
	dataDir = flag.String("data", "data", "Path to data files relative to current working dir.")
	port    = flag.Int("port", 8080, "Webserver port number.")
	remote  = flag.String("remote", "http://gravatar.com/avatar", "Use this gravatar-compatible avatar service if "+
		"no avatar is found, use 'none' for no remote.")
	dflt = flag.String("default", "resources/mm", "Default avatar. Use 'remote' to use the default of the remote "+
		"service, or 'remote:<option>' to use a builtin default. For example: 'remote:monsterid'. This is passes as "+
		"'?d=monsterid' to the remote service. See https://nl.gravatar.com/site/implement/images/.")
)

var (
	defaultImage  = "resources/mm"
	remoteUrl     = ""
	remoteDefault = ""
)

type Avatar struct {
	size int
	data []byte
}

type Request struct {
	hash string
	size int
}

func readImage(reader io.Reader, size int) *Avatar {
	b := new(bytes.Buffer)
	if _, e := io.Copy(b, reader); e != nil {
		log.Printf("Could not read image", e)
		return nil
	}
	return &Avatar{size: -1, data: b.Bytes()}
}

func readFromFile(filename string, size int) *Avatar {
	file, err := os.Open(filename)
	if err != nil {
		log.Printf("Error reading file: %v", err)
		return nil
	}
	defer file.Close()
	return readImage(file, size)
}

func retrieveFromLocal(request Request) *Avatar {
	return readFromFile(createPath(request.hash), request.size)
}

// Retrieves the avatar from the remote service, returning nil if there is no avatar or it could not be retrieved
func retrieveFromRemote(request Request) *Avatar {
	if remoteUrl == "" {
		return nil
	}
	options := fmt.Sprintf("s=%d", request.size)
	if remoteDefault != "" {
		options += "&d=" + remoteDefault
	}
	remote := remoteUrl + "/" + request.hash + "?" + options
	resp, err2 := http.Get(remote)
	if err2 != nil {
		log.Printf("Remote lookup of %s failed with error: %s", remote, err2)
		return nil
	}
	if resp.StatusCode == 404 {
		log.Printf("Avatar not found on remote")
		return nil
	}
	return readImage(resp.Body, request.size)
}

func createPath(hash string) string {
	return fmt.Sprintf("%s/%s", *dataDir, hash)
}

func writeAvatarResult(w http.ResponseWriter, avatar *Avatar) {
	b := bytes.NewBuffer(avatar.data)
	_, err := io.Copy(w, b)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func retrieveImage(request Request, w http.ResponseWriter, r *http.Request) *Avatar {
	avatar := retrieveFromLocal(request)
	if avatar == nil {
		avatar = retrieveFromRemote(request)
	}
	if avatar == nil {
		avatar = readFromFile(defaultImage, request.size)
	}
	if avatar == nil {
		avatar = readFromFile("resources/mm", request.size)
	}
	return avatar
}

// VERY SIMPLE NOT THREAD-SAFE CACHE, JUST FOR NOW!
var cache = make(map[Request]*Avatar)

func loadImage(request Request, w http.ResponseWriter, r *http.Request) {
	log.Printf("Loading image: %v", request)
	avatar := cache[request]
	if avatar == nil {
		avatar = retrieveImage(request, w, r)
		cache[request] = avatar
	}
	if avatar == nil {
		http.NotFound(w, r)
	} else {
		writeAvatarResult(w, avatar)
	}
}

func avatarHandler(w http.ResponseWriter, r *http.Request, title string) {
	r.ParseForm()
	sizeParam := r.FormValue("s")
	size := 80
	if sizeParam != "" {
		if s, err := strconv.Atoi(sizeParam); err == nil {
			size = s
			if size > 512 { size = 512 }
			if size < 8 { size = 8 }
		}
	}
	loadImage(Request{hash: title, size: size}, w, r)
}

var templates = template.Must(template.ParseFiles("resources/upload.html", "resources/view.html"))

func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
	err := templates.ExecuteTemplate(w, tmpl+".html", data)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func uploadHandler(w http.ResponseWriter, r *http.Request, title string) {
	renderTemplate(w, "upload", map[string]string{"Title": "Upload your avatar"})
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
	email := r.FormValue("email")
	log.Printf("Saving image for email address: %v", email)
	file, _, err := r.FormFile("datafile")
	if err != nil {
		log.Print("Error: ", err)
		fmt.Fprintf(w, "
Please chooce a file to upload
")
		return
	}

	h := md5.New()
	io.WriteString(h, email) // FIXME trim and toLowerCase!
	hash := fmt.Sprintf("%x", h.Sum(nil))
	filename := createPath(hash)

	f, err := os.Create(filename)
	if err != nil {
		log.Print("Error: ", err)
		fmt.Fprintf(w, "
Error while uploading file
")
		return
	}
	defer f.Close()
	io.Copy(f, file)

	renderTemplate(w, "view", map[string]string{"Avatar": fmt.Sprintf("/avatar/%s", hash)})
}

var validPath = regexp.MustCompile("^/(avatar|upload)/([a-zA-Z0-9]+)(/.*)?$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//		log.Printf("Request: %v", r)
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			log.Print("Invalid request: ", r.URL)
			http.NotFound(w, r)
			return
		}
		log.Print("Handling request: ", r.URL)
		fn(w, r, m[2])
	}
}

var fallbackDefaultPattern = regexp.MustCompile("^fallback:([a-zA-Z]+)$")

func main() {
	iniflags.Parse()

	log.Printf("data dir = %s\n", *dataDir)
	address := fmt.Sprintf(":%d", *port)

	if *remote == "none" {
		remoteUrl = ""
	} else {
		remoteUrl = *remote
		log.Printf("Missig avatars will be redirected to %s", remoteUrl)
	}

	if *dflt == "fallback" {
		log.Printf("Default image will be provided by the remote service if configured")
		remoteDefault = ""
	} else if builtin := fallbackDefaultPattern.FindStringSubmatch(*dflt); builtin != nil {
		remoteDefault = builtin[1]
		log.Printf("Default image will be provided by the remote service using '?d=%s' if a remote is configured", remoteDefault)
	} else {
		defaultImage = *dflt
		remoteDefault = "404"
		log.Printf("Using %s as default image", defaultImage)
	}

	log.Printf("Listening on %s\n", address)
	http.HandleFunc("/avatar/", makeHandler(avatarHandler))
	http.HandleFunc("/upload/form/", makeHandler(uploadHandler))
	http.HandleFunc("/upload/save/", makeHandler(saveHandler))
	x := http.ListenAndServe(address, nil)
	fmt.Println("Result: ", x)
}
<commit_msg>Add cache information to response headers<commit_after>package main

import (
	"bytes"
	"crypto/md5"
	"flag"
	"fmt"
	"github.com/vharitonsky/iniflags"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"regexp"
	"strconv"
)

var (
	dataDir = flag.String("data", "data", "Path to data files relative to current working dir.")
	port    = flag.Int("port", 8080, "Webserver port number.")
	remote  = flag.String("remote", "http://gravatar.com/avatar", "Use this gravatar-compatible avatar service if "+
		"no avatar is found, use 'none' for no remote.")
	dflt = flag.String("default", "resources/mm", "Default avatar. Use 'remote' to use the default of the remote "+
		"service, or 'remote:<option>' to use a builtin default. For example: 'remote:monsterid'. This is passes as "+
		"'?d=monsterid' to the remote service. See https://nl.gravatar.com/site/implement/images/.")
)

var (
	defaultImage  = "resources/mm"
	remoteUrl     = ""
	remoteDefault = ""
)

type Avatar struct {
	size int
	data []byte
	// below are used in header fields
	cacheControl string
	lastModified string
}

type Request struct {
	hash string
	size int
}

func readImage(reader io.Reader, size int) *Avatar {
	b := new(bytes.Buffer)
	if _, e := io.Copy(b, reader); e != nil {
		log.Printf("Could not read image", e)
		return nil
	}
	// FIXME scale if necessary
	return &Avatar{size: size, data: b.Bytes()}
}

func readFromFile(filename string, size int) *Avatar {
	file, err := os.Open(filename)
	if err != nil {
		log.Printf("Error reading file: %v", err)
		return nil
	}
	defer file.Close()
	avatar := readImage(file, size)
	avatar.cacheControl = "300"
	if info, e := os.Stat(filename); e == nil {
		timestamp := info.ModTime().UTC()
		avatar.lastModified = timestamp.Format(http.TimeFormat)
	} else {
		avatar.lastModified = "Sat, 1 Jan 2000 12:00:00 GMT"
	}
	return avatar
}

func retrieveFromLocal(request Request) *Avatar {
	return readFromFile(createPath(request.hash), request.size)
}

// Retrieves the avatar from the remote service, returning nil if there is no avatar or it could not be retrieved
func retrieveFromRemote(request Request) *Avatar {
	if remoteUrl == "" {
		return nil
	}
	options := fmt.Sprintf("s=%d", request.size)
	if remoteDefault != "" {
		options += "&d=" + remoteDefault
	}
	remote := remoteUrl + "/" + request.hash + "?" + options
	log.Printf("Retrieving from: %s", remote)
	resp, err2 := http.Get(remote)
	if err2 != nil {
		log.Printf("Remote lookup of %s failed with error: %s", remote, err2)
		return nil
	}
	if resp.StatusCode == 404 {
		log.Printf("Avatar not found on remote")
		return nil
	}
	avatar := readImage(resp.Body, request.size)
	avatar.cacheControl = resp.Header.Get("Cache-Control")
	avatar.lastModified = resp.Header.Get("Last-Modified")
	return avatar
}

func createPath(hash string) string {
	return fmt.Sprintf("%s/%s", *dataDir, hash)
}

func setHeaderField(w http.ResponseWriter, key string, value string) {
	if value != "" { w.Header().Set(key, value) }
}

func writeAvatarResult(w http.ResponseWriter, avatar *Avatar) {
	setHeaderField(w, "Last-Modified", avatar.lastModified)
	setHeaderField(w, "Cache-Control", avatar.cacheControl)
	b := bytes.NewBuffer(avatar.data)
	_, err := io.Copy(w, b)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func retrieveImage(request Request, w http.ResponseWriter, r *http.Request) *Avatar {
	avatar := retrieveFromLocal(request)
	if avatar == nil {
		avatar = retrieveFromRemote(request)
	}
	if avatar == nil {
		avatar = readFromFile(defaultImage, request.size)
	}
	if avatar == nil {
		avatar = readFromFile("resources/mm", request.size)
	}
	return avatar
}

// VERY SIMPLE NOT THREAD-SAFE NEVER-EXPIRING CACHE, JUST FOR NOW!
var cache = make(map[Request]*Avatar)

func loadImage(request Request, w http.ResponseWriter, r *http.Request) {
	log.Printf("Loading image: %v", request)
	avatar := cache[request]
	if avatar == nil {
		avatar = retrieveImage(request, w, r)
		cache[request] = avatar
	}
	if avatar == nil {
		http.NotFound(w, r)
	} else {
		writeAvatarResult(w, avatar)
	}
}

func avatarHandler(w http.ResponseWriter, r *http.Request, title string) {
	r.ParseForm()
	sizeParam := r.FormValue("s")
	size := 80
	if sizeParam != "" {
		if s, err := strconv.Atoi(sizeParam); err == nil {
			size = s
			if size > 512 { size = 512 }
			if size < 8 { size = 8 }
		}
	}
	loadImage(Request{hash: title, size: size}, w, r)
}

var templates = template.Must(template.ParseFiles("resources/upload.html", "resources/view.html"))

func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
	err := templates.ExecuteTemplate(w, tmpl+".html", data)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func uploadHandler(w http.ResponseWriter, r *http.Request, title string) {
	renderTemplate(w, "upload", map[string]string{"Title": "Upload your avatar"})
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
	email := r.FormValue("email")
	log.Printf("Saving image for email address: %v", email)
	file, _, err := r.FormFile("datafile")
	if err != nil {
		log.Print("Error: ", err)
		fmt.Fprintf(w, "
Please chooce a file to upload
")
		return
	}

	h := md5.New()
	io.WriteString(h, email) // FIXME trim and toLowerCase!
	hash := fmt.Sprintf("%x", h.Sum(nil))
	filename := createPath(hash)

	f, err := os.Create(filename)
	if err != nil {
		log.Print("Error: ", err)
		fmt.Fprintf(w, "
Error while uploading file
")
		return
	}
	defer f.Close()
	io.Copy(f, file)

	renderTemplate(w, "view", map[string]string{"Avatar": fmt.Sprintf("/avatar/%s", hash)})
}

var validPath = regexp.MustCompile("^/(avatar|upload)/([a-zA-Z0-9]+)(/.*)?$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//		log.Printf("Request: %v", r)
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			log.Print("Invalid request: ", r.URL)
			http.NotFound(w, r)
			return
		}
		log.Print("Handling request: ", r.URL)
		fn(w, r, m[2])
	}
}

var fallbackDefaultPattern = regexp.MustCompile("^remote:([a-zA-Z]+)$")

func main() {
	iniflags.Parse()

	log.Printf("data dir = %s\n", *dataDir)
	address := fmt.Sprintf(":%d", *port)

	if *remote == "none" {
		remoteUrl = ""
	} else {
		remoteUrl = *remote
		log.Printf("Missig avatars will be redirected to %s", remoteUrl)
	}

	if *dflt == "fallback" {
		log.Printf("Default image will be provided by the remote service if configured")
		remoteDefault = ""
	} else if builtin := fallbackDefaultPattern.FindStringSubmatch(*dflt); builtin != nil {
		remoteDefault = builtin[1]
		log.Printf("Default image will be provided by the remote service using '?d=%s' if a remote is configured", remoteDefault)
	} else {
		defaultImage = *dflt
		remoteDefault = "404"
		log.Printf("Using %s as default image", defaultImage)
	}

	log.Printf("Listening on %s\n", address)
	http.HandleFunc("/avatar/", makeHandler(avatarHandler))
	http.HandleFunc("/upload/form/", makeHandler(uploadHandler))
	http.HandleFunc("/upload/save/", makeHandler(saveHandler))
	x := http.ListenAndServe(address, nil)
	fmt.Println("Result: ", x)
}
<|endoftext|>


<commit_before>package main

// TODO: add TLS to listener and admin
// TODO: add TLS to uplink (including reloads)
// TODO: better names for resp New*er
// TODO: proper logging
// TODO: guard config access with a mutex
// TODO: keepalive?

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"
)

const CONFIG_FILE = "config.json"
const READ_TIME_LIMIT = 5 * time.Second

func main() {
	config, err := loadConfig(CONFIG_FILE)
	if err != nil {
		panic(err)
	}
	proxy := NewRedisProxy(config)
	proxy.run()
}

////////////////////////////////////////
// RedisProxyConfig

type RedisProxyConfig struct {
	UplinkAddr   string `json:"uplink_addr"`
	UplinkUseTLS bool   `json:"uplink_use_tls"`
	ListenOn     string `json:"listen_on"`
	AdminOn      string `json:"admin_on"`
}

func loadConfig(fname string) (*RedisProxyConfig, error) {
	configJson, err := ioutil.ReadFile(fname)
	if err != nil {
		return nil, err
	}
	var config RedisProxyConfig
	return &config, json.Unmarshal(configJson, &config)
}

////////////////////////////////////////
// RedisProxy

const TICKET_COUNT = 100

type RedisProxy struct {
	config                *RedisProxyConfig
	enterExecutionChannel chan bool
	leaveExecutionChannel chan bool
}

func NewRedisProxy(config *RedisProxyConfig) *RedisProxy {
	return &RedisProxy{
		config:                config,
		enterExecutionChannel: make(chan bool, TICKET_COUNT),
		leaveExecutionChannel: make(chan bool, TICKET_COUNT)}
}

func (proxy *RedisProxy) run() {
	listener, err := net.Listen("tcp", proxy.config.ListenOn)
	if err != nil {
		panic(err)
	}

	fmt.Println("Listening on", proxy.config.ListenOn)

	go proxy.watchSignals()
	go proxy.executionLimiter()
	go proxy.publishAdminInterface()

	for {
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}
		go proxy.handleClient(conn)
	}
}

func (proxy *RedisProxy) reloadConfig() {
	newConfig, err := loadConfig(CONFIG_FILE)
	if err != nil {
		fmt.Printf("Got an error while loading %s: %s.  Keeping old config.", CONFIG_FILE, err)
		return
	}

	if err := proxy.verifyNewConfig(newConfig); err != nil {
		fmt.Printf("Can not reload into new config: %s.  Keeping old config.", err)
		return
	}
	proxy.config = newConfig
}

func (proxy *RedisProxy) watchSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)

	for {
		s := <-c
		fmt.Printf("Got signal: %v, reloading config\n", s)
		proxy.reloadConfig()
	}
}

func (proxy *RedisProxy) activeRequests() int {
	return TICKET_COUNT - len(proxy.enterExecutionChannel)
}

func (proxy *RedisProxy) verifyNewConfig(newConfig *RedisProxyConfig) error {
	config := proxy.config
	if config.ListenOn != newConfig.ListenOn {
		return errors.New("New config must have the same listen_on address as the old one.")
	}
	if config.AdminOn != newConfig.AdminOn {
		return errors.New("New config must have the same admin_on address as the old one.")
	}
	return nil
}

func (proxy *RedisProxy) executionLimiter() {
	for i := 0; i < TICKET_COUNT; i++ {
		proxy.enterExecutionChannel <- true
	}
	for {
		<-proxy.leaveExecutionChannel
		proxy.enterExecutionChannel <- true
	}
}

func (proxy *RedisProxy) EnterExecution() {
	<-proxy.enterExecutionChannel
}

func (proxy *RedisProxy) LeaveExecution() {
	proxy.leaveExecutionChannel <- true
}

func (proxy *RedisProxy) ExecuteCall(block func() ([]byte, error)) ([]byte, error) {
	proxy.EnterExecution()
	defer proxy.LeaveExecution()

	return block()
}

func (proxy *RedisProxy) handleClient(cliConn net.Conn) {
	fmt.Println("Handling new client:", cliConn)

	// TODO: catch and log panics
	defer cliConn.Close()
	cliReader := NewReader(bufio.NewReader(cliConn))
	cliWriter := bufio.NewWriter(cliConn)

	uplinkAddr := proxy.config.UplinkAddr

	fmt.Println("Dialing", uplinkAddr)
	uplinkConn, err := net.Dial("tcp", uplinkAddr)
	if err != nil {
		fmt.Printf("Dial error: %v\n", err)
		return
	}
	defer func() {
		// TODO: does this actually close the right connection
		// after reloads?
		uplinkConn.Close()
	}()
	uplinkReader := NewReader(bufio.NewReader(uplinkConn))
	uplinkWriter := bufio.NewWriter(uplinkConn)

	for {
		req, err := cliReader.ReadObject()
		if err != nil {
			fmt.Printf("Read error: %v\n", err)
			return
		}
		fmt.Printf("%s\n", req)

		resp, err := proxy.ExecuteCall(func() ([]byte, error) {
			currUplinkAddr := proxy.config.UplinkAddr
			if uplinkAddr != currUplinkAddr {
				uplinkAddr = currUplinkAddr
				fmt.Println("Redialing", uplinkAddr)
				uplinkConn.Close()
				uplinkConn, err = net.Dial("tcp", uplinkAddr)
				if err != nil {
					return nil, err
				}
				uplinkReader = NewReader(bufio.NewReader(uplinkConn))
				uplinkWriter = bufio.NewWriter(uplinkConn)
			}

			uplinkWriter.Write(req)
			uplinkWriter.Flush()

			uplinkConn.SetReadDeadline(time.Now().Add(READ_TIME_LIMIT))
			return uplinkReader.ReadObject()
		})
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			return
		}

		cliWriter.Write(resp)
		cliWriter.Flush()
	}
}
<commit_msg>Cosmetic cleanup.<commit_after>package main

// TODO: add TLS to listener and admin
// TODO: add TLS to uplink (including reloads)
// TODO: better names for resp New*er
// TODO: proper logging
// TODO: guard config access with a mutex
// TODO: keepalive?

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"
)

const CONFIG_FILE = "config.json"
const READ_TIME_LIMIT = 5 * time.Second

func main() {
	config, err := loadConfig(CONFIG_FILE)
	if err != nil {
		panic(err)
	}
	proxy := NewRedisProxy(config)
	proxy.run()
}

////////////////////////////////////////
// RedisProxyConfig

type RedisProxyConfig struct {
	UplinkAddr   string `json:"uplink_addr"`
	UplinkUseTLS bool   `json:"uplink_use_tls"`
	ListenOn     string `json:"listen_on"`
	AdminOn      string `json:"admin_on"`
}

func loadConfig(fname string) (*RedisProxyConfig, error) {
	configJson, err := ioutil.ReadFile(fname)
	if err != nil {
		return nil, err
	}
	var config RedisProxyConfig
	return &config, json.Unmarshal(configJson, &config)
}

////////////////////////////////////////
// RedisProxy

const TICKET_COUNT = 100

type RedisProxy struct {
	config                *RedisProxyConfig
	enterExecutionChannel chan bool
	leaveExecutionChannel chan bool
}

func NewRedisProxy(config *RedisProxyConfig) *RedisProxy {
	return &RedisProxy{
		config:                config,
		enterExecutionChannel: make(chan bool, TICKET_COUNT),
		leaveExecutionChannel: make(chan bool, TICKET_COUNT)}
}

func (proxy *RedisProxy) run() {
	listener, err := net.Listen("tcp", proxy.config.ListenOn)
	if err != nil {
		panic(err)
	}

	fmt.Println("Listening on", proxy.config.ListenOn)

	go proxy.watchSignals()
	go proxy.executionLimiter()
	go proxy.publishAdminInterface()

	for {
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}
		go proxy.handleClient(conn)
	}
}

func (proxy *RedisProxy) reloadConfig() {
	newConfig, err := loadConfig(CONFIG_FILE)
	if err != nil {
		fmt.Printf("Got an error while loading %s: %s.  Keeping old config.", CONFIG_FILE, err)
		return
	}

	if err := proxy.verifyNewConfig(newConfig); err != nil {
		fmt.Printf("Can not reload into new config: %s.  Keeping old config.", err)
		return
	}
	proxy.config = newConfig
}

func (proxy *RedisProxy) watchSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP)

	for {
		s := <-c
		fmt.Printf("Got signal: %v, reloading config\n", s)
		proxy.reloadConfig()
	}
}

func (proxy *RedisProxy) activeRequests() int {
	return TICKET_COUNT - len(proxy.enterExecutionChannel)
}

func (proxy *RedisProxy) verifyNewConfig(newConfig *RedisProxyConfig) error {
	config := proxy.config
	if config.ListenOn != newConfig.ListenOn {
		return errors.New("New config must have the same listen_on address as the old one.")
	}
	if config.AdminOn != newConfig.AdminOn {
		return errors.New("New config must have the same admin_on address as the old one.")
	}
	return nil
}

func (proxy *RedisProxy) executionLimiter() {
	for i := 0; i < TICKET_COUNT; i++ {
		proxy.enterExecutionChannel <- true
	}
	for {
		<-proxy.leaveExecutionChannel
		proxy.enterExecutionChannel <- true
	}
}

func (proxy *RedisProxy) enterExecution() {
	<-proxy.enterExecutionChannel
}

func (proxy *RedisProxy) leaveExecution() {
	proxy.leaveExecutionChannel <- true
}

func (proxy *RedisProxy) executeCall(block func() ([]byte, error)) ([]byte, error) {
	proxy.enterExecution()
	defer proxy.leaveExecution()

	return block()
}

func (proxy *RedisProxy) handleClient(cliConn net.Conn) {
	fmt.Println("Handling new client:", cliConn)

	// TODO: catch and log panics
	defer cliConn.Close()
	cliReader := NewReader(bufio.NewReader(cliConn))
	cliWriter := bufio.NewWriter(cliConn)

	uplinkAddr := proxy.config.UplinkAddr

	fmt.Println("Dialing", uplinkAddr)
	uplinkConn, err := net.Dial("tcp", uplinkAddr)
	if err != nil {
		fmt.Printf("Dial error: %v\n", err)
		return
	}
	defer func() {
		// TODO: does this actually close the right connection
		// after reloads?
		uplinkConn.Close()
	}()
	uplinkReader := NewReader(bufio.NewReader(uplinkConn))
	uplinkWriter := bufio.NewWriter(uplinkConn)

	for {
		req, err := cliReader.ReadObject()
		if err != nil {
			fmt.Printf("Read error: %v\n", err)
			return
		}

		resp, err := proxy.executeCall(func() ([]byte, error) {
			currUplinkAddr := proxy.config.UplinkAddr
			if uplinkAddr != currUplinkAddr {
				uplinkAddr = currUplinkAddr
				fmt.Println("Redialing", uplinkAddr)
				uplinkConn.Close()
				uplinkConn, err = net.Dial("tcp", uplinkAddr)
				if err != nil {
					return nil, err
				}
				uplinkReader = NewReader(bufio.NewReader(uplinkConn))
				uplinkWriter = bufio.NewWriter(uplinkConn)
			}

			uplinkWriter.Write(req)
			uplinkWriter.Flush()

			uplinkConn.SetReadDeadline(time.Now().Add(READ_TIME_LIMIT))
			return uplinkReader.ReadObject()
		})
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			return
		}

		cliWriter.Write(resp)
		cliWriter.Flush()
	}
}
<|endoftext|>


<commit_before>package main

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

	openrtb "gopkg.in/bsm/openrtb.v1"
)

const (
	ACSIp       string = "127.0.0.1"
	ACSPort            = 9986
	BankerIp           = "127.0.0.1"
	BankerPort         = 9985
	BidderPort         = 7654
	BidderWin          = 7653
	BidderEvent        = 7652
)

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s request took %s", name, elapsed)
}

func track(fn http.HandlerFunc, name string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		defer timeTrack(time.Now(), name)
		fn(w, req)
	}
}

func main() {
	var agentsConfigFile = flag.String("config", "", "Configuration file in JSON.")
	flag.Parse()
	if *agentsConfigFile == "" {
		log.Fatal("You should provide a configuration file.")
	}

	// http client to pace agents (note that it's pointer)
	client := &http.Client{}

	// load configuration
	agents, err := LoadAgentsFromFile(*agentsConfigFile)
	if err != nil {
		log.Fatal(err)
	}
	for _, agent := range agents {
		agent.RegisterAgent(client, ACSIp, ACSPort)
		agent.StartPacer(client, BankerIp, BankerPort)
	}

	mux := http.NewServeMux()

	mux.HandleFunc("/", track(func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		var (
			ok    bool = true
			tmpOk bool = true
		)
		enc := json.NewEncoder(w)
		req, err := openrtb.ParseRequest(r.Body)

		if err != nil {
			log.Println("ERROR", err.Error())
			w.WriteHeader(204) // respond with 'no bid'
			return
		}

		log.Println("INFO Received bid request", *req.Id)

		ids := externalIdsFromRequest(req)
		res := emptyResponseWithOneSeat(req)

		for _, agent := range agents {
			res, tmpOk = agent.DoBid(req, res, ids)
			ok = tmpOk || ok
		}

		if ok {
			w.Header().Set("Content-type", "application/json")
			w.Header().Add("x-openrtb-version", "2.1")
			w.WriteHeader(http.StatusOK)
			enc.Encode(res)
			return
		}
		log.Println("No bid.")
		w.WriteHeader(204)

	}, "bidding"))

	go http.ListenAndServe(fmt.Sprintf(":%d", BidderPort), mux)

	evemux := http.NewServeMux()
	evemux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		w.WriteHeader(http.StatusOK)
		io.WriteString(w, "")
		log.Println("Event!")
	})
	go http.ListenAndServe(fmt.Sprintf(":%d", BidderEvent), evemux)

	winmux := http.NewServeMux()
	winmux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		w.WriteHeader(http.StatusOK)
		io.WriteString(w, "")
		log.Println("Win!")
	})
	go http.ListenAndServe(fmt.Sprintf(":%d", BidderWin), winmux)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	select {
	case <-c:
		// Implement remove agent from ACS
		for _, agent := range agents {
			agent.UnregisterAgent(client, ACSIp, ACSPort)
		}
		fmt.Println("Leaving...")
	}
}
<commit_msg>Outputting port configs at startup<commit_after>package main

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

	openrtb "gopkg.in/bsm/openrtb.v1"
)

const (
	ACSIp       string = "127.0.0.1"
	ACSPort            = 9986
	BankerIp           = "127.0.0.1"
	BankerPort         = 9985
	BidderPort         = 7654
	BidderWin          = 7653
	BidderEvent        = 7652
)

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s request took %s", name, elapsed)
}

func track(fn http.HandlerFunc, name string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		defer timeTrack(time.Now(), name)
		fn(w, req)
	}
}

func printPortConfigs() {
	log.Printf("Bidder port: %d", BidderPort)
	log.Printf("Win port: %d", BidderWin)
	log.Printf("Event port: %d", BidderEvent)
}

func main() {
	var agentsConfigFile = flag.String("config", "", "Configuration file in JSON.")
	flag.Parse()
	if *agentsConfigFile == "" {
		log.Fatal("You should provide a configuration file.")
	}

	printPortConfigs()

	// http client to pace agents (note that it's pointer)
	client := &http.Client{}

	// load configuration
	agents, err := LoadAgentsFromFile(*agentsConfigFile)
	if err != nil {
		log.Fatal(err)
	}
	for _, agent := range agents {
		agent.RegisterAgent(client, ACSIp, ACSPort)
		agent.StartPacer(client, BankerIp, BankerPort)
	}

	mux := http.NewServeMux()

	mux.HandleFunc("/", track(func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		var (
			ok    bool = true
			tmpOk bool = true
		)
		enc := json.NewEncoder(w)
		req, err := openrtb.ParseRequest(r.Body)

		if err != nil {
			log.Println("ERROR", err.Error())
			w.WriteHeader(204) // respond with 'no bid'
			return
		}

		log.Println("INFO Received bid request", *req.Id)

		ids := externalIdsFromRequest(req)
		res := emptyResponseWithOneSeat(req)

		for _, agent := range agents {
			res, tmpOk = agent.DoBid(req, res, ids)
			ok = tmpOk || ok
		}

		if ok {
			w.Header().Set("Content-type", "application/json")
			w.Header().Add("x-openrtb-version", "2.1")
			w.WriteHeader(http.StatusOK)
			enc.Encode(res)
			return
		}
		log.Println("No bid.")
		w.WriteHeader(204)

	}, "bidding"))

	go http.ListenAndServe(fmt.Sprintf(":%d", BidderPort), mux)

	evemux := http.NewServeMux()
	evemux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		w.WriteHeader(http.StatusOK)
		io.WriteString(w, "")
		log.Println("Event!")
	})
	go http.ListenAndServe(fmt.Sprintf(":%d", BidderEvent), evemux)

	winmux := http.NewServeMux()
	winmux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()
		w.WriteHeader(http.StatusOK)
		io.WriteString(w, "")
		log.Println("Win!")
	})
	go http.ListenAndServe(fmt.Sprintf(":%d", BidderWin), winmux)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	select {
	case <-c:
		// Implement remove agent from ACS
		for _, agent := range agents {
			agent.UnregisterAgent(client, ACSIp, ACSPort)
		}
		fmt.Println("Leaving...")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"os"
	"regexp"
	"strconv"
	"strings"

	logrus "github.com/Sirupsen/logrus"
	docopt "github.com/docopt/docopt-go"

	"github.com/9seconds/ah/app/commands"
	"github.com/9seconds/ah/app/environments"
	"github.com/9seconds/ah/app/slices"
	"github.com/9seconds/ah/app/utils"
)

const docoptOptions = `ah - A better history.

Ah is a better way to traverse the history of your shell prompts. You can
store an outputs of your commands, you can search with regular expressions
out of box, bookmark commands etc.

You may want to check detailed readme at https://github.com/9seconds/ah

Just a short reminder on possible subcommands:
    - s  - shows extended output from your HISTFILE
    - b  - bookmarks any command you want to have a faster access.
    - e  - executes a command by its bookmark name or history number.
    - t  - traces an output of the command and stores it safely.
    - l  - lists you an output of the command.
    - lb - lists available bookmarks.
    - rb - removes bookmarks.
    - gt - garbage collecting of the traces. Cleans old outputs.
    - gb - garbage collecting of the bookmarks. Swipes out old ones.

Usage:
    ah [options] s [-z] [-g PATTERN] [<lastNcommands> | <startFromNCommand> <finishByMCommand>]
    ah [options] b <commandNumber> <bookmarkAs>
    ah [options] e [-x] [-y] <commandNumberOrBookMarkName>
    ah [options] t [-x] [-y] [--] <command>...
    ah [options] l <numberOfCommandYouWantToCheck>
    ah [options] lb
    ah [options] rb <bookmarkToRemove>...
    ah [options] (gt | gb) (--keepLatest <keepLatest> | --olderThan <olderThan> | --all)
    ah (-h | --help)
    ah --version

Options:
    -s SHELL, --shell=SHELL
       Shell flavour you are using.
       By default, ah will do some shallow investigations.
    -f HISTFILE, --histfile=HISTFILE
       The path to a history file.
       By default ah will try to use default history file of your shell.
    -t HISTTIMEFORMAT, --histtimeformat=HISTTIMEFORMAT
       A time format for history output. Will use $HISTTIMEFORMAT by default.
    -d APPDIR, --appdir=APPDIR
       A place where ah has to store its data.
    -m TMPDIR, --tmpdir=TMPDIR
       A temporary place where ah stores an output. Set it only if you need it.
    -g PATTERN, --grep PATTERN
       A pattern to filter command lines. It is regular expression if no -f option is set.
    -y, --tty
       Allocates pseudo-tty is necessary.
    -x, --run-in-real-shell
       Runs a command in real interactive shell.
    -z, --fuzzy
       Interpret -g pattern as fuzzy match string.
    -v, --debug
       Shows a debug log of command execution.`

const version = "ah 0.12"

var validateBookmarkName = utils.CreateRegexp(`^[A-Za-z_]\w*$`)

type executor func(map[string]interface{}, *environments.Environment)

func main() {
	defer func() {
		if exc := recover(); exc != nil {
			utils.Logger.Fatal(exc)
		}
	}()

	arguments, err := docopt.Parse(docoptOptions, nil, true, version, false)
	if err != nil {
		panic(err)
	}

	if arguments["--debug"].(bool) {
		utils.EnableLogging()
	} else {
		utils.DisableLogging()
	}

	env := new(environments.Environment)
	argShell := arguments["--shell"]
	if argShell == nil {
		env.DiscoverShell()
	} else {
		env.SetShell(argShell.(string))
	}

	argHistFile := arguments["--histfile"]
	if argHistFile == nil {
		env.DiscoverHistFile()
	} else {
		env.SetHistFile(argHistFile.(string))
	}

	argHistTimeFormat := arguments["--histtimeformat"]
	if argHistTimeFormat == nil {
		env.DiscoverHistTimeFormat()
	} else {
		env.SetHistTimeFormat(argHistTimeFormat.(string))
	}

	argAppDir := arguments["--appdir"]
	if argAppDir == nil {
		env.DiscoverAppDir()
	} else {
		env.SetAppDir(argAppDir.(string))
	}

	argTmpDir := arguments["--tmpdir"]
	if argTmpDir == nil {
		env.DiscoverTmpDir()
	} else {
		env.SetTmpDir(argTmpDir.(string))
	}

	utils.Logger.WithFields(logrus.Fields{
		"arguments":   arguments,
		"environment": env,
	}).Debug("Ready to start")

	utils.Logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetTracesDir(), 0777),
	}).Info("Create traces dir")
	utils.Logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetBookmarksDir(), 0777),
	}).Info("Create bookmarks dir")
	utils.Logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetTmpDir(), 0777),
	}).Info("Create create temporary dir")

	var exec executor
	switch {
	case arguments["t"].(bool):
		utils.Logger.Info("Execute command 'tee'")
		exec = executeTee
	case arguments["s"].(bool):
		utils.Logger.Info("Execute command 'show'")
		exec = executeShow
	case arguments["l"].(bool):
		utils.Logger.Info("Execute command 'listTrace'")
		exec = executeListTrace
	case arguments["b"].(bool):
		utils.Logger.Info("Execute command 'listTrace'")
		exec = executeListTrace
	case arguments["e"].(bool):
		utils.Logger.Info("Execute command 'execute'")
		exec = executeExec
	case arguments["lb"].(bool):
		utils.Logger.Info("Execute command 'listBookmarks'")
		exec = executeListBookmarks
	case arguments["rb"].(bool):
		utils.Logger.Info("Execute command 'removeBookmarks'")
		exec = executeRemoveBookmarks
	case arguments["gt"].(bool) || arguments["gb"].(bool):
		utils.Logger.Info("Execute command 'gc'")
		exec = executeGC
	default:
		utils.Logger.Panic("Unknown command. Please be more precise")
		return
	}
	exec(arguments, env)
}

func executeTee(arguments map[string]interface{}, env *environments.Environment) {
	cmds := arguments["<command>"].([]string)
	cmd := strings.Join(cmds, " ")
	tty := arguments["--tty"].(bool)
	interactive := arguments["--run-in-real-shell"].(bool)

	utils.Logger.WithFields(logrus.Fields{
		"command":     cmd,
		"pseudo-tty":  tty,
		"interactive": interactive,
	}).Info("Arguments of 'tee'")

	commands.Tee(cmd, interactive, tty, env)
}

func executeShow(arguments map[string]interface{}, env *environments.Environment) {
	slice, err := slices.ExtractSlice(
		arguments["<lastNcommands>"],
		arguments["<startFromNCommand>"],
		arguments["<finishByMCommand>"])
	if err != nil {
		utils.Logger.Panic(err)
	}

	var filter *utils.Regexp
	if arguments["--grep"] != nil {
		query := arguments["--grep"].(string)
		if arguments["--fuzzy"].(bool) {
			regex := new(bytes.Buffer)
			for _, character := range query {
				regex.WriteString(".*?")
				regex.WriteString(regexp.QuoteMeta(string(character)))
			}
			regex.WriteString(".*?")
			query = regex.String()
		}
		filter = utils.CreateRegexp(query)
	}

	utils.Logger.WithFields(logrus.Fields{
		"slice":  slice,
		"filter": filter,
	}).Info("Arguments of 'show'")

	commands.Show(slice, filter, env)
}

func executeListTrace(arguments map[string]interface{}, env *environments.Environment) {
	cmd := arguments["<numberOfCommandYouWantToCheck>"].(string)

	utils.Logger.WithFields(logrus.Fields{
		"cmd": cmd,
	}).Info("Arguments of 'listTrace'")

	commands.ListTrace(cmd, env)
}

func executeBookmark(arguments map[string]interface{}, env *environments.Environment) {
	number, err := strconv.Atoi(arguments["<commandNumber>"].(string))
	if err != nil {
		utils.Logger.Panicf("Cannot understand command number: %d", number)
	}

	bookmarkAs := arguments["<bookmarkAs>"].(string)
	if !validateBookmarkName.Match(bookmarkAs) {
		utils.Logger.Panic("Incorrect bookmark name!")
	}

	utils.Logger.WithFields(logrus.Fields{
		"commandNumber": number,
		"bookmarkAs":    bookmarkAs,
	}).Info("Arguments of 'bookmark'")

	commands.Bookmark(number, bookmarkAs, env)
}

func executeExec(arguments map[string]interface{}, env *environments.Environment) {
	commandNumberOrBookMarkName := arguments["<commandNumberOrBookMarkName>"].(string)
	tty := arguments["--tty"].(bool)
	interactive := arguments["--run-in-real-shell"].(bool)

	utils.Logger.WithFields(logrus.Fields{
		"commandNumberOrBookMarkName": commandNumberOrBookMarkName,
		"tty":         tty,
		"interactive": interactive,
	}).Info("Arguments of 'bookmark'")

	commandNumber, err := strconv.Atoi(commandNumberOrBookMarkName)
	switch {
	case err == nil:
		utils.Logger.Info("Execute command number ", commandNumber)
		commands.ExecuteCommandNumber(commandNumber, interactive, tty, env)
	case validateBookmarkName.Match(commandNumberOrBookMarkName):
		utils.Logger.Info("Execute bookmark ", commandNumberOrBookMarkName)
		commands.ExecuteBookmark(commandNumberOrBookMarkName, interactive, tty, env)
	default:
		utils.Logger.Panic("Incorrect bookmark name! It should be started with alphabet letter, and alphabet or digits after!")
	}
}

func executeGC(arguments map[string]interface{}, env *environments.Environment) {
	gcDir := commands.GcTracesDir
	if arguments["gb"].(bool) {
		gcDir = commands.GcBookmarksDir
	}

	var gcType commands.GcType
	stringParam := "1"
	switch {
	case arguments["--keepLatest"].(bool):
		gcType = commands.GcKeepLatest
		stringParam = arguments["<keepLatest>"].(string)
	case arguments["--olderThan"].(bool):
		gcType = commands.GcOlderThan
		stringParam = arguments["<keepLatest>"].(string)
	case arguments["--all"].(bool):
		gcType = commands.GcAll
	default:
		utils.Logger.Panic("Unknown subcommand command")
	}

	param, err := strconv.Atoi(stringParam)
	if err != nil {
		utils.Logger.Panic(err)
	} else if param <= 0 {
		utils.Logger.Panic("Parameter of garbage collection has to be > 0")
	}

	utils.Logger.WithFields(logrus.Fields{
		"gcType": gcType,
		"param":  param,
	}).Info("Arguments")

	commands.GC(gcType, gcDir, param, env)
}

func executeListBookmarks(_ map[string]interface{}, env *environments.Environment) {
	commands.ListBookmarks(env)
}

func executeRemoveBookmarks(arguments map[string]interface{}, env *environments.Environment) {
	bookmarks, ok := arguments["<bookmarkToRemove>"].([]string)
	if !ok || bookmarks == nil || len(bookmarks) == 0 {
		utils.Logger.Info("Nothing to do here")
		return
	}

	for _, bookmark := range bookmarks {
		if !validateBookmarkName.Match(bookmark) {
			utils.Logger.WithFields(logrus.Fields{
				"bookmark": bookmark,
			}).Panicf("Bookmark name %s is invalid", bookmark)
		}
	}

	commands.RemoveBookmarks(bookmarks, env)
}
<commit_msg>Update ah options with auto commands<commit_after>package main

import (
	"bytes"
	"os"
	"regexp"
	"strconv"
	"strings"

	logrus "github.com/Sirupsen/logrus"
	docopt "github.com/docopt/docopt-go"

	"github.com/9seconds/ah/app/commands"
	"github.com/9seconds/ah/app/environments"
	"github.com/9seconds/ah/app/slices"
	"github.com/9seconds/ah/app/utils"
)

const docoptOptions = `ah - A better history.

Ah is a better way to traverse the history of your shell prompts. You can
store an outputs of your commands, you can search with regular expressions
out of box, bookmark commands etc.

You may want to check detailed readme at https://github.com/9seconds/ah

Just a short reminder on possible subcommands:
    - s  - shows extended output from your HISTFILE
    - b  - bookmarks any command you want to have a faster access.
    - e  - executes a command by its bookmark name or history number.
    - t  - traces an output of the command and stores it safely.
    - l  - lists you an output of the command.
    - lb - lists available bookmarks.
    - rb - removes bookmarks.
    - gt - garbage collecting of the traces. Cleans old outputs.
    - gb - garbage collecting of the bookmarks. Swipes out old ones.
	- ad - add command to the list of auto ah'ed
	- ar - remove commands from the list of auto ah'ed
	- al - list of commands which should be auto ah'ed

Usage:
    ah [options] s [-z] [-g PATTERN] [<lastNcommands> | <startFromNCommand> <finishByMCommand>]
    ah [options] b <commandNumber> <bookmarkAs>
    ah [options] e [-x] [-y] <commandNumberOrBookMarkName>
    ah [options] t [-x] [-y] [--] <command>...
    ah [options] l <numberOfCommandYouWantToCheck>
    ah [options] lb
    ah [options] rb <bookmarkToRemove>...
    ah [options] (gt | gb) (--keepLatest <keepLatest> | --olderThan <olderThan> | --all)
	ah [options] al
	ah [options] (ad | al) <command>...
    ah (-h | --help)
    ah --version

Options:
    -s SHELL, --shell=SHELL
       Shell flavour you are using.
       By default, ah will do some shallow investigations.
    -f HISTFILE, --histfile=HISTFILE
       The path to a history file.
       By default ah will try to use default history file of your shell.
    -t HISTTIMEFORMAT, --histtimeformat=HISTTIMEFORMAT
       A time format for history output. Will use $HISTTIMEFORMAT by default.
    -d APPDIR, --appdir=APPDIR
       A place where ah has to store its data.
    -m TMPDIR, --tmpdir=TMPDIR
       A temporary place where ah stores an output. Set it only if you need it.
    -g PATTERN, --grep PATTERN
       A pattern to filter command lines. It is regular expression if no -f option is set.
    -y, --tty
       Allocates pseudo-tty is necessary.
    -x, --run-in-real-shell
       Runs a command in real interactive shell.
    -z, --fuzzy
       Interpret -g pattern as fuzzy match string.
    -v, --debug
       Shows a debug log of command execution.`

const version = "ah 0.12"

var validateBookmarkName = utils.CreateRegexp(`^[A-Za-z_]\w*$`)

type executor func(map[string]interface{}, *environments.Environment)

func main() {
	defer func() {
		if exc := recover(); exc != nil {
			utils.Logger.Fatal(exc)
		}
	}()

	arguments, err := docopt.Parse(docoptOptions, nil, true, version, false)
	if err != nil {
		panic(err)
	}

	if arguments["--debug"].(bool) {
		utils.EnableLogging()
	} else {
		utils.DisableLogging()
	}

	env := new(environments.Environment)
	argShell := arguments["--shell"]
	if argShell == nil {
		env.DiscoverShell()
	} else {
		env.SetShell(argShell.(string))
	}

	argHistFile := arguments["--histfile"]
	if argHistFile == nil {
		env.DiscoverHistFile()
	} else {
		env.SetHistFile(argHistFile.(string))
	}

	argHistTimeFormat := arguments["--histtimeformat"]
	if argHistTimeFormat == nil {
		env.DiscoverHistTimeFormat()
	} else {
		env.SetHistTimeFormat(argHistTimeFormat.(string))
	}

	argAppDir := arguments["--appdir"]
	if argAppDir == nil {
		env.DiscoverAppDir()
	} else {
		env.SetAppDir(argAppDir.(string))
	}

	argTmpDir := arguments["--tmpdir"]
	if argTmpDir == nil {
		env.DiscoverTmpDir()
	} else {
		env.SetTmpDir(argTmpDir.(string))
	}

	utils.Logger.WithFields(logrus.Fields{
		"arguments":   arguments,
		"environment": env,
	}).Debug("Ready to start")

	utils.Logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetTracesDir(), 0777),
	}).Info("Create traces dir")
	utils.Logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetBookmarksDir(), 0777),
	}).Info("Create bookmarks dir")
	utils.Logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetTmpDir(), 0777),
	}).Info("Create create temporary dir")

	var exec executor
	switch {
	case arguments["t"].(bool):
		utils.Logger.Info("Execute command 'tee'")
		exec = executeTee
	case arguments["s"].(bool):
		utils.Logger.Info("Execute command 'show'")
		exec = executeShow
	case arguments["l"].(bool):
		utils.Logger.Info("Execute command 'listTrace'")
		exec = executeListTrace
	case arguments["b"].(bool):
		utils.Logger.Info("Execute command 'listTrace'")
		exec = executeListTrace
	case arguments["e"].(bool):
		utils.Logger.Info("Execute command 'execute'")
		exec = executeExec
	case arguments["lb"].(bool):
		utils.Logger.Info("Execute command 'listBookmarks'")
		exec = executeListBookmarks
	case arguments["rb"].(bool):
		utils.Logger.Info("Execute command 'removeBookmarks'")
		exec = executeRemoveBookmarks
	case arguments["gt"].(bool) || arguments["gb"].(bool):
		utils.Logger.Info("Execute command 'gc'")
		exec = executeGC
	default:
		utils.Logger.Panic("Unknown command. Please be more precise")
		return
	}
	exec(arguments, env)
}

func executeTee(arguments map[string]interface{}, env *environments.Environment) {
	cmds := arguments["<command>"].([]string)
	cmd := strings.Join(cmds, " ")
	tty := arguments["--tty"].(bool)
	interactive := arguments["--run-in-real-shell"].(bool)

	utils.Logger.WithFields(logrus.Fields{
		"command":     cmd,
		"pseudo-tty":  tty,
		"interactive": interactive,
	}).Info("Arguments of 'tee'")

	commands.Tee(cmd, interactive, tty, env)
}

func executeShow(arguments map[string]interface{}, env *environments.Environment) {
	slice, err := slices.ExtractSlice(
		arguments["<lastNcommands>"],
		arguments["<startFromNCommand>"],
		arguments["<finishByMCommand>"])
	if err != nil {
		utils.Logger.Panic(err)
	}

	var filter *utils.Regexp
	if arguments["--grep"] != nil {
		query := arguments["--grep"].(string)
		if arguments["--fuzzy"].(bool) {
			regex := new(bytes.Buffer)
			for _, character := range query {
				regex.WriteString(".*?")
				regex.WriteString(regexp.QuoteMeta(string(character)))
			}
			regex.WriteString(".*?")
			query = regex.String()
		}
		filter = utils.CreateRegexp(query)
	}

	utils.Logger.WithFields(logrus.Fields{
		"slice":  slice,
		"filter": filter,
	}).Info("Arguments of 'show'")

	commands.Show(slice, filter, env)
}

func executeListTrace(arguments map[string]interface{}, env *environments.Environment) {
	cmd := arguments["<numberOfCommandYouWantToCheck>"].(string)

	utils.Logger.WithFields(logrus.Fields{
		"cmd": cmd,
	}).Info("Arguments of 'listTrace'")

	commands.ListTrace(cmd, env)
}

func executeBookmark(arguments map[string]interface{}, env *environments.Environment) {
	number, err := strconv.Atoi(arguments["<commandNumber>"].(string))
	if err != nil {
		utils.Logger.Panicf("Cannot understand command number: %d", number)
	}

	bookmarkAs := arguments["<bookmarkAs>"].(string)
	if !validateBookmarkName.Match(bookmarkAs) {
		utils.Logger.Panic("Incorrect bookmark name!")
	}

	utils.Logger.WithFields(logrus.Fields{
		"commandNumber": number,
		"bookmarkAs":    bookmarkAs,
	}).Info("Arguments of 'bookmark'")

	commands.Bookmark(number, bookmarkAs, env)
}

func executeExec(arguments map[string]interface{}, env *environments.Environment) {
	commandNumberOrBookMarkName := arguments["<commandNumberOrBookMarkName>"].(string)
	tty := arguments["--tty"].(bool)
	interactive := arguments["--run-in-real-shell"].(bool)

	utils.Logger.WithFields(logrus.Fields{
		"commandNumberOrBookMarkName": commandNumberOrBookMarkName,
		"tty":         tty,
		"interactive": interactive,
	}).Info("Arguments of 'bookmark'")

	commandNumber, err := strconv.Atoi(commandNumberOrBookMarkName)
	switch {
	case err == nil:
		utils.Logger.Info("Execute command number ", commandNumber)
		commands.ExecuteCommandNumber(commandNumber, interactive, tty, env)
	case validateBookmarkName.Match(commandNumberOrBookMarkName):
		utils.Logger.Info("Execute bookmark ", commandNumberOrBookMarkName)
		commands.ExecuteBookmark(commandNumberOrBookMarkName, interactive, tty, env)
	default:
		utils.Logger.Panic("Incorrect bookmark name! It should be started with alphabet letter, and alphabet or digits after!")
	}
}

func executeGC(arguments map[string]interface{}, env *environments.Environment) {
	gcDir := commands.GcTracesDir
	if arguments["gb"].(bool) {
		gcDir = commands.GcBookmarksDir
	}

	var gcType commands.GcType
	stringParam := "1"
	switch {
	case arguments["--keepLatest"].(bool):
		gcType = commands.GcKeepLatest
		stringParam = arguments["<keepLatest>"].(string)
	case arguments["--olderThan"].(bool):
		gcType = commands.GcOlderThan
		stringParam = arguments["<keepLatest>"].(string)
	case arguments["--all"].(bool):
		gcType = commands.GcAll
	default:
		utils.Logger.Panic("Unknown subcommand command")
	}

	param, err := strconv.Atoi(stringParam)
	if err != nil {
		utils.Logger.Panic(err)
	} else if param <= 0 {
		utils.Logger.Panic("Parameter of garbage collection has to be > 0")
	}

	utils.Logger.WithFields(logrus.Fields{
		"gcType": gcType,
		"param":  param,
	}).Info("Arguments")

	commands.GC(gcType, gcDir, param, env)
}

func executeListBookmarks(_ map[string]interface{}, env *environments.Environment) {
	commands.ListBookmarks(env)
}

func executeRemoveBookmarks(arguments map[string]interface{}, env *environments.Environment) {
	bookmarks, ok := arguments["<bookmarkToRemove>"].([]string)
	if !ok || bookmarks == nil || len(bookmarks) == 0 {
		utils.Logger.Info("Nothing to do here")
		return
	}

	for _, bookmark := range bookmarks {
		if !validateBookmarkName.Match(bookmark) {
			utils.Logger.WithFields(logrus.Fields{
				"bookmark": bookmark,
			}).Panicf("Bookmark name %s is invalid", bookmark)
		}
	}

	commands.RemoveBookmarks(bookmarks, env)
}
<|endoftext|>


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

package verror

import (
	"fmt"

	"v.io/v23/vdl"
)

func init() {
	// TODO(bprosnitz) Remove this old-style registration.
	// We must register the error conversion functions between vdl.WireError and
	// the standard error interface with the vdl package.  This allows the vdl
	// package to have minimal dependencies.
	vdl.RegisterNativeError(WireToNative, WireFromNative)

	// New-style error registration.
	vdl.RegisterNative(ErrorToNative, ErrorFromNative)
}

// TODO(toddw): rename Error{To,From}Native to Wire{To,From}Native, after we've
// switched to the new vdl Encoder/Decoder, and the old functions are no longer
// used.

// ErrorToNative converts from the wire to native representation of errors.
func ErrorToNative(wire *vdl.WireError, native *error) error {
	if wire == nil {
		*native = nil
		return nil
	}
	e := new(E)
	*native = e
	return WireToNative(*wire, e)
}

// ErrorFromNative converts from the native to wire representation of errors.
func ErrorFromNative(wire **vdl.WireError, native error) error {
	if native == nil {
		*wire = nil
		return nil
	}
	if *wire == nil {
		*wire = new(vdl.WireError)
	}
	return WireFromNative(*wire, native)
}

// FromWire is a convenience for generated code to convert wire errors into
// native errors.
func FromWire(wire *vdl.WireError) error {
	var native error
	if err := ErrorToNative(wire, &native); err != nil {
		native = err
	}
	return native
}

// WireToNative converts from vdl.WireError to verror.E, which
// implements the standard go error interface.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireToNative(wire vdl.WireError, native *E) error {
	*native = E{
		ID:     ID(wire.Id),
		Action: retryToAction(wire.RetryCode),
		Msg:    wire.Msg,
	}
	for _, p := range wire.ParamList {
		var pNative interface{}
		if err := vdl.Convert(&pNative, p); err != nil {
			// It's questionable what to do if the conversion fails, or similarly if
			// the conversion ends up with a *vdl.Value, rather than a native Go
			// value.
			//
			// At the moment, for both cases we plug the *vdl.Value or conversion
			// error into the native params.  The idea is that this will still be more
			// useful to the user, since they'll still have the error Id and Action.
			//
			// TODO(toddw): Consider whether there is a better strategy.
			pNative = err
		}
		native.ParamList = append(native.ParamList, pNative)
	}
	return nil
}

// WireFromNative converts from the standard go error interface to
// verror.E, and then to vdl.WireError.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireFromNative(wire *vdl.WireError, native error) error {
	e := ExplicitConvert(ErrUnknown, "", "", "", native)
	*wire = vdl.WireError{
		Id:        string(ErrorID(e)),
		RetryCode: retryFromAction(Action(e)),
		Msg:       e.Error(),
	}
	for _, p := range params(e) {
		var pWire *vdl.Value
		if err := vdl.Convert(&pWire, p); err != nil {
			// It's questionable what to do here if the conversion fails, similarly to
			// the conversion failure above in WireToNative.
			//
			// TODO(toddw): Consider whether there is a better strategy.
			pWire = vdl.StringValue(nil, err.Error())
		}
		wire.ParamList = append(wire.ParamList, pWire)
	}
	return nil
}

func retryToAction(retry vdl.WireRetryCode) ActionCode {
	switch retry {
	case vdl.WireRetryCodeNoRetry:
		return NoRetry
	case vdl.WireRetryCodeRetryConnection:
		return RetryConnection
	case vdl.WireRetryCodeRetryRefetch:
		return RetryRefetch
	case vdl.WireRetryCodeRetryBackoff:
		return RetryBackoff
	}
	// Backoff to no retry by default.
	return NoRetry
}

func retryFromAction(action ActionCode) vdl.WireRetryCode {
	switch action.RetryAction() {
	case NoRetry:
		return vdl.WireRetryCodeNoRetry
	case RetryConnection:
		return vdl.WireRetryCodeRetryConnection
	case RetryRefetch:
		return vdl.WireRetryCodeRetryRefetch
	case RetryBackoff:
		return vdl.WireRetryCodeRetryBackoff
	}
	// Backoff to no retry by default.
	return vdl.WireRetryCodeNoRetry
}

// VDLRead implements the logic to read x from dec.
//
// Unlike regular VDLRead implementations, this handles the case where the
// decoder contains a nil value, to make code generation simpler.
func VDLRead(dec vdl.Decoder, x *error) error {
	if err := dec.StartValue(); err != nil {
		return err
	}
	if dec.IsNil() {
		if (dec.StackDepth() == 1 || dec.IsAny()) && !vdl.Compatible(vdl.ErrorType, dec.Type()) {
			return fmt.Errorf("incompatible error, from %v", dec.Type())
		}
		*x = nil
		return dec.FinishValue()
	}
	dec.IgnoreNextStartValue()
	var wire vdl.WireError
	if err := wire.VDLRead(dec); err != nil {
		return err
	}
	nativePtr := new(E)
	if err := WireToNative(wire, nativePtr); err != nil {
		return err
	}
	*x = nativePtr
	return nil
}

// VDLWrite implements the logic to write x to enc.
//
// Unlike regular VDLWrite implementations, this handles the case where x
// contains a nil value, to make code generation simpler.
func VDLWrite(enc vdl.Encoder, x error) error {
	if x == nil {
		return enc.NilValue(vdl.ErrorType)
	}
	var wire vdl.WireError
	if err := WireFromNative(&wire, x); err != nil {
		return err
	}
	return wire.VDLWrite(enc)
}
<commit_msg>Change verror WireToNative behavior.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package verror

import (
	"fmt"

	"v.io/v23/vdl"
)

func init() {
	// TODO(bprosnitz) Remove this old-style registration.
	// We must register the error conversion functions between vdl.WireError and
	// the standard error interface with the vdl package.  This allows the vdl
	// package to have minimal dependencies.
	vdl.RegisterNativeError(WireToNative, WireFromNative)

	// New-style error registration.
	vdl.RegisterNative(ErrorToNative, ErrorFromNative)
}

// TODO(toddw): rename Error{To,From}Native to Wire{To,From}Native, after we've
// switched to the new vdl Encoder/Decoder, and the old functions are no longer
// used.

// ErrorToNative converts from the wire to native representation of errors.
func ErrorToNative(wire *vdl.WireError, native *error) error {
	if wire == nil {
		*native = nil
		return nil
	}
	e := new(E)
	*native = e
	return WireToNative(*wire, e)
}

// ErrorFromNative converts from the native to wire representation of errors.
func ErrorFromNative(wire **vdl.WireError, native error) error {
	if native == nil {
		*wire = nil
		return nil
	}
	if *wire == nil {
		*wire = new(vdl.WireError)
	}
	return WireFromNative(*wire, native)
}

// FromWire is a convenience for generated code to convert wire errors into
// native errors.
func FromWire(wire *vdl.WireError) error {
	var native error
	if err := ErrorToNative(wire, &native); err != nil {
		native = err
	}
	return native
}

// WireToNative converts from vdl.WireError to verror.E, which
// implements the standard go error interface.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireToNative(wire vdl.WireError, native *E) error {
	*native = E{
		ID:     ID(wire.Id),
		Action: retryToAction(wire.RetryCode),
		Msg:    wire.Msg,
	}
	for _, pWire := range wire.ParamList {
		var pNative interface{}
		if err := vdl.Convert(&pNative, pWire); err != nil {
			// It's questionable what to do if the conversion fails, rather than
			// ending up with a native Go value.
			//
			// At the moment, we plug the *vdl.Value into the native params.  The idea
			// is that this will still be more useful to the user, since they'll still
			// have the error Id and Action.
			//
			// TODO(toddw): Consider whether there is a better strategy.
			pNative = pWire
		}
		native.ParamList = append(native.ParamList, pNative)
	}
	return nil
}

// WireFromNative converts from the standard go error interface to
// verror.E, and then to vdl.WireError.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireFromNative(wire *vdl.WireError, native error) error {
	e := ExplicitConvert(ErrUnknown, "", "", "", native)
	*wire = vdl.WireError{
		Id:        string(ErrorID(e)),
		RetryCode: retryFromAction(Action(e)),
		Msg:       e.Error(),
	}
	for _, pNative := range params(e) {
		var pWire *vdl.Value
		if err := vdl.Convert(&pWire, pNative); err != nil {
			// It's questionable what to do here if the conversion fails, similarly to
			// the conversion failure above in WireToNative.
			//
			// TODO(toddw): Consider whether there is a better strategy.
			pWire = vdl.StringValue(nil, err.Error())
		}
		wire.ParamList = append(wire.ParamList, pWire)
	}
	return nil
}

func retryToAction(retry vdl.WireRetryCode) ActionCode {
	switch retry {
	case vdl.WireRetryCodeNoRetry:
		return NoRetry
	case vdl.WireRetryCodeRetryConnection:
		return RetryConnection
	case vdl.WireRetryCodeRetryRefetch:
		return RetryRefetch
	case vdl.WireRetryCodeRetryBackoff:
		return RetryBackoff
	}
	// Backoff to no retry by default.
	return NoRetry
}

func retryFromAction(action ActionCode) vdl.WireRetryCode {
	switch action.RetryAction() {
	case NoRetry:
		return vdl.WireRetryCodeNoRetry
	case RetryConnection:
		return vdl.WireRetryCodeRetryConnection
	case RetryRefetch:
		return vdl.WireRetryCodeRetryRefetch
	case RetryBackoff:
		return vdl.WireRetryCodeRetryBackoff
	}
	// Backoff to no retry by default.
	return vdl.WireRetryCodeNoRetry
}

// VDLRead implements the logic to read x from dec.
//
// Unlike regular VDLRead implementations, this handles the case where the
// decoder contains a nil value, to make code generation simpler.
func VDLRead(dec vdl.Decoder, x *error) error {
	if err := dec.StartValue(); err != nil {
		return err
	}
	if dec.IsNil() {
		if (dec.StackDepth() == 1 || dec.IsAny()) && !vdl.Compatible(vdl.ErrorType, dec.Type()) {
			return fmt.Errorf("incompatible error, from %v", dec.Type())
		}
		*x = nil
		return dec.FinishValue()
	}
	dec.IgnoreNextStartValue()
	var wire vdl.WireError
	if err := wire.VDLRead(dec); err != nil {
		return err
	}
	nativePtr := new(E)
	if err := WireToNative(wire, nativePtr); err != nil {
		return err
	}
	*x = nativePtr
	return nil
}

// VDLWrite implements the logic to write x to enc.
//
// Unlike regular VDLWrite implementations, this handles the case where x
// contains a nil value, to make code generation simpler.
func VDLWrite(enc vdl.Encoder, x error) error {
	if x == nil {
		return enc.NilValue(vdl.ErrorType)
	}
	var wire vdl.WireError
	if err := WireFromNative(&wire, x); err != nil {
		return err
	}
	return wire.VDLWrite(enc)
}
<|endoftext|>


<commit_before>/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2017 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package main

import (
	"fmt"
	"os"

	"github.com/deckarep/blade/cmd"
)

func main() {
	if err := cmd.RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<commit_msg>Minor tweak<commit_after>/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2017 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package main

import (
	"log"

	"github.com/deckarep/blade/cmd"
)

func main() {
	if err := cmd.RootCmd.Execute(); err != nil {
		log.Fatalf("Failed to executed RootCmd with err:", err.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
  "fbtron/fbtron"

  "fmt"
  "runtime"
  "time"
)

func main() {
  fmt.Println("Starting")

  // Tell Go to use all of the processors
  num_cpus := runtime.NumCPU()
  runtime.GOMAXPROCS(num_cpus)

  sendchannels := make([]chan string, num_cpus)
  recvchannels := make([]chan fbtron.Simulation, num_cpus)
  for n := range sendchannels {
    sendchannels[n] = make(chan string, 1)
    recvchannels[n] = make(chan fbtron.Simulation, 1)
    go fbtron.RunSimulation(sendchannels[n], recvchannels[n])
  }

  // TODO: Start http thread ...

  // TEMP
  for {
    time.Sleep(time.Second * 3)

    for n := range sendchannels {
      sendchannels[n] <- "ping"
      sim := <-recvchannels[n]

      var bestplayer *fbtron.Player
      var bestwpd float64

      for _, player := range sim.All_players {
        if bestplayer == nil || player.WinsPerDraft() > bestwpd {
          bestplayer = player
          bestwpd = player.WinsPerDraft()
        }
      }

      fmt.Printf("t%d: ran %d seasons, best player is %s (%.1f)\n",
                  n, sim.Num_seasons, bestplayer.GetName(), bestwpd)
    }
  }
}
<commit_msg>--threads and --cpus flags<commit_after>package main

import (
  "fbtron/fbtron"

  "flag"
  "fmt"
  "runtime"
  "time"
)

var num_threads = flag.Int(
    "threads", 0, "Number of threads to start (0 = number of cpus)")
var num_cpus = flag.Int(
    "cpus", 0, "Number of CPUs to use (0 = all on system)")

func main() {
  // Tell Go to use all of the processors
  if *num_cpus == 0 {
    *num_cpus = runtime.NumCPU()
  }
  runtime.GOMAXPROCS(*num_cpus)
  if *num_threads == 0 {
    *num_threads = *num_cpus
  }

  fmt.Printf("Starting %d threads on %d cpus\n", *num_threads, *num_cpus)

  sendchannels := make([]chan string, *num_threads)
  recvchannels := make([]chan fbtron.Simulation, *num_threads)
  for n := range sendchannels {
    sendchannels[n] = make(chan string, 1)
    recvchannels[n] = make(chan fbtron.Simulation, 1)
    go fbtron.RunSimulation(sendchannels[n], recvchannels[n])
  }

  // TODO: Start http thread ...

  // TEMP
  for {
    time.Sleep(time.Second * 3)

    for n := range sendchannels {
      sendchannels[n] <- "ping"
      sim := <-recvchannels[n]

      var bestplayer *fbtron.Player
      var bestwpd float64

      for _, player := range sim.All_players {
        if bestplayer == nil || player.WinsPerDraft() > bestwpd {
          bestplayer = player
          bestwpd = player.WinsPerDraft()
        }
      }

      fmt.Printf("t%d: ran %d seasons, best player is %s (%.1f)\n",
                  n, sim.Num_seasons, bestplayer.GetName(), bestwpd)
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gl

// #include "gl.h"
import "C"

// Vertex Arrays
type VertexArray Object

func GenVertexArray() VertexArray {
	var a C.GLuint
	C.glGenVertexArrays(1, &a)
	return VertexArray(a)
}

func GenVertexArrays(arrays []VertexArray) {
	if len(arrays) > 0 {
		C.glGenVertexArrays(C.GLsizei(len(arrays)), (*C.GLuint)(&arrays[0]))
	}
}

func (array VertexArray) Delete() {
	C.glDeleteVertexArrays(1, (*C.GLuint)(&array))
}

func DeleteVertexArrays(arrays []VertexArray) {
	if len(arrays) > 0 {
		C.glDeleteVertexArrays(C.GLsizei(len(arrays)), (*C.GLuint)(&arrays[0]))
	}
}

func (array VertexArray) Bind() {
	C.glBindVertexArray(C.GLuint(array))
}
<commit_msg>Add function to unbind a vao (fix #143)<commit_after>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gl

// #include "gl.h"
import "C"

// Vertex Arrays
type VertexArray Object

func GenVertexArray() VertexArray {
	var a C.GLuint
	C.glGenVertexArrays(1, &a)
	return VertexArray(a)
}

func GenVertexArrays(arrays []VertexArray) {
	if len(arrays) > 0 {
		C.glGenVertexArrays(C.GLsizei(len(arrays)), (*C.GLuint)(&arrays[0]))
	}
}

func (array VertexArray) Delete() {
	C.glDeleteVertexArrays(1, (*C.GLuint)(&array))
}

func DeleteVertexArrays(arrays []VertexArray) {
	if len(arrays) > 0 {
		C.glDeleteVertexArrays(C.GLsizei(len(arrays)), (*C.GLuint)(&arrays[0]))
	}
}

func (array VertexArray) Bind() {
	C.glBindVertexArray(C.GLuint(array))
}

func (array VertexArray) Unbind() {
	C.glBindVertexArray(C.GLuint(0))
}
<|endoftext|>


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

package main

import (
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.10.0"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	lookup := func(context *cmd.Context) error {
		command := plugin{}
		return command.Run(context, nil)
	}
	m := cmd.BuildBaseManager(name, version, header, lookup)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.AppStart{})
	m.Register(&tsuru.AppStop{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	m.Register(platformList{})
	m.Register(&pluginInstall{})
	m.Register(&pluginRemove{})
	m.Register(&pluginList{})
	m.Register(swap{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<commit_msg>cmd/tsuru: version 0.10.1<commit_after>// Copyright 2014 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.10.1"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	lookup := func(context *cmd.Context) error {
		command := plugin{}
		return command.Run(context, nil)
	}
	m := cmd.BuildBaseManager(name, version, header, lookup)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.AppStart{})
	m.Register(&tsuru.AppStop{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	m.Register(platformList{})
	m.Register(&pluginInstall{})
	m.Register(&pluginRemove{})
	m.Register(&pluginList{})
	m.Register(swap{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/jolshevski/chester/api"
)

func main() {
	app := api.New()

	// Define configuration flags
	modulepath := flag.String("modulepath", "", "Directory containing module release tarballs to serve. Required.")
	binding := flag.String("binding", ":8080", "Golang ListenAndServe binding")
	fileurl := flag.String("fileurl", "", "URL to the base of the URL which the module tarballs are being served from")
	flag.Parse()

	// Configure the API
	app.Config["modulepath"] = *modulepath
	app.Config["binding"] = *binding
	app.Config["fileurl"] = *fileurl

	// Start the API server
	app.Listen()
}
<commit_msg>Adding fileurl default<commit_after>package main

import (
	"flag"
	"github.com/jolshevski/chester/api"
)

func main() {
	app := api.New()

	// Define configuration flags
	modulepath := flag.String("modulepath", "", "Directory containing module release tarballs to serve. Required.")
	binding := flag.String("binding", ":8080", "Golang ListenAndServe binding")
	fileurl := flag.String("fileurl", "/v3/files", "URL to the base of the URL which the module tarballs are being served from")
	flag.Parse()

	// Configure the API
	app.Config["modulepath"] = *modulepath
	app.Config["binding"] = *binding
	app.Config["fileurl"] = *fileurl

	// Start the API server
	app.Listen()
}
<|endoftext|>