<commit_before>package main

import (
	"net/http"
	"hash"
	"crypto/md5"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha512"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"encoding/hex"
	"io"
	"io/ioutil"
	"errors"
	"strings"
	"math"
	"log"
)

const (
	HASH_SHA1 = iota
	HASH_SHA256
	HASH_SHA512
	HASH_SHA512_384
)

func GetMD5(input []byte) ([]byte) {
	hash := md5.New()
	hash.Write(input)
	return hash.Sum(nil)
}

func GetSHA512(input []byte) ([]byte) {
	sha := sha512.New()
	sha.Write(input)
	return sha.Sum(nil)
}

func GetSHA256(input []byte) ([]byte) {
	sha := sha256.New()
	sha.Write(input)
	return sha.Sum(nil)
}

func GetHMAC(hashType int, input, key []byte) ([]byte) {
	var hash func() hash.Hash

	switch hashType {
		case HASH_SHA1: {
			hash = sha1.New
		}
		case HASH_SHA256: {
			hash = sha256.New
		}
		case HASH_SHA512: {
			hash = sha512.New
		}
		case HASH_SHA512_384: {
			hash = sha512.New384
		}
	}

	hmac := hmac.New(hash, []byte(key))
	hmac.Write(input)
	return hmac.Sum(nil)
}

func HexEncodeToString(input []byte) (string) {
	return hex.EncodeToString(input)
}

func Base64Decode(input string) ([]byte, error) {
	result, err := base64.StdEncoding.DecodeString(input)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func Base64Encode(input []byte) (string) {
	return base64.StdEncoding.EncodeToString(input)
}

func RoundFloat(x float64, prec int) float64 {
  	var rounder float64
	pow := math.Pow(10, float64(prec))
	intermed := x * pow
	_, frac := math.Modf(intermed)
	intermed += .5
	x = .5
	if frac < 0.0 {
		x = -.5
		intermed -= 1
	}
	if frac >= x {
		rounder = math.Ceil(intermed)
	} else {
		rounder = math.Floor(intermed)
	}

	return rounder / pow
}

func CalculateAmountWithFee(amount, fee float64) (float64) {
	return amount + CalculateFee(amount, fee)
}

func CalculateFee(amount, fee float64) (float64) {
	return amount * (fee / 100)
}

func CalculatePercentageDifference(amount, secondAmount float64) (float64) {
	return (secondAmount - amount) / amount * 100
}

func CalculateNetProfit(amount, priceThen, priceNow, costs float64) (float64) {
	return (priceNow * amount) - (priceThen * amount) - costs
}

func SendHTTPRequest(method, path string, headers map[string]string, body io.Reader) (string, error) {
	result := strings.ToUpper(method)

	if result != "POST" && result != "GET" {
		return "", errors.New("Invalid HTTP method specified.")
	}

	req, err := http.NewRequest(method, path, body)

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

	for k, v := range headers {
		req.Header.Add(k, v)
	}

	httpClient := &http.Client{}
	resp, err := httpClient.Do(req)

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

	contents, err := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

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

	return string(contents), nil
}

func SendHTTPGetRequest(url string, jsonDecode bool, result interface{}) (err error) {
	res, err := http.Get(url)

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

	if res.StatusCode != 200 {
		log.Printf("HTTP status code: %d\n", res.StatusCode)
		return errors.New("Status code was not 200.")
	}

	contents, _ := ioutil.ReadAll(res.Body)
	//log.Printf("Recieved raw: %s\n", string(contents))
	defer res.Body.Close()

	if jsonDecode {
		err := json.Unmarshal(contents, &result)

		if err != nil {
			return errors.New("Unable to JSON decode body.")
		}
	} else {
		result = contents
	}

	return nil
}<commit_msg>Added common JSON decode function.<commit_after>package main

import (
	"net/http"
	"hash"
	"crypto/md5"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha512"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"encoding/hex"
	"io"
	"io/ioutil"
	"errors"
	"strings"
	"math"
	"log"
)

const (
	HASH_SHA1 = iota
	HASH_SHA256
	HASH_SHA512
	HASH_SHA512_384
)

func GetMD5(input []byte) ([]byte) {
	hash := md5.New()
	hash.Write(input)
	return hash.Sum(nil)
}

func GetSHA512(input []byte) ([]byte) {
	sha := sha512.New()
	sha.Write(input)
	return sha.Sum(nil)
}

func GetSHA256(input []byte) ([]byte) {
	sha := sha256.New()
	sha.Write(input)
	return sha.Sum(nil)
}

func GetHMAC(hashType int, input, key []byte) ([]byte) {
	var hash func() hash.Hash

	switch hashType {
		case HASH_SHA1: {
			hash = sha1.New
		}
		case HASH_SHA256: {
			hash = sha256.New
		}
		case HASH_SHA512: {
			hash = sha512.New
		}
		case HASH_SHA512_384: {
			hash = sha512.New384
		}
	}

	hmac := hmac.New(hash, []byte(key))
	hmac.Write(input)
	return hmac.Sum(nil)
}

func HexEncodeToString(input []byte) (string) {
	return hex.EncodeToString(input)
}

func Base64Decode(input string) ([]byte, error) {
	result, err := base64.StdEncoding.DecodeString(input)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func Base64Encode(input []byte) (string) {
	return base64.StdEncoding.EncodeToString(input)
}

func RoundFloat(x float64, prec int) float64 {
  	var rounder float64
	pow := math.Pow(10, float64(prec))
	intermed := x * pow
	_, frac := math.Modf(intermed)
	intermed += .5
	x = .5
	if frac < 0.0 {
		x = -.5
		intermed -= 1
	}
	if frac >= x {
		rounder = math.Ceil(intermed)
	} else {
		rounder = math.Floor(intermed)
	}

	return rounder / pow
}

func CalculateAmountWithFee(amount, fee float64) (float64) {
	return amount + CalculateFee(amount, fee)
}

func CalculateFee(amount, fee float64) (float64) {
	return amount * (fee / 100)
}

func CalculatePercentageDifference(amount, secondAmount float64) (float64) {
	return (secondAmount - amount) / amount * 100
}

func CalculateNetProfit(amount, priceThen, priceNow, costs float64) (float64) {
	return (priceNow * amount) - (priceThen * amount) - costs
}

func SendHTTPRequest(method, path string, headers map[string]string, body io.Reader) (string, error) {
	result := strings.ToUpper(method)

	if result != "POST" && result != "GET" {
		return "", errors.New("Invalid HTTP method specified.")
	}

	req, err := http.NewRequest(method, path, body)

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

	for k, v := range headers {
		req.Header.Add(k, v)
	}

	httpClient := &http.Client{}
	resp, err := httpClient.Do(req)

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

	contents, err := ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()

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

	return string(contents), nil
}

func SendHTTPGetRequest(url string, jsonDecode bool, result interface{}) (err error) {
	res, err := http.Get(url)

	if err != nil {
		return err
	}

	if res.StatusCode != 200 {
		log.Printf("HTTP status code: %d\n", res.StatusCode)
		return errors.New("Status code was not 200.")
	}

	contents, err := ioutil.ReadAll(res.Body)

	if err != nil {
		return err
	}

	defer res.Body.Close()

	if jsonDecode {
		err := JSONDecode(contents, &result)

		if err != nil {
			return err
		}
	} else {
		result = &contents
	}

	return nil
}

func JSONDecode(data []byte, to interface{}) (error) {
	err := json.Unmarshal(data, &to)

	if err != nil {
		return err
	}

	return nil
}<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/user"
	"path"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/route53"
)

type recordSet struct {
	name         string
	value        string // ip
	rsType       string
	ttl          int64
	hostedZoneID string
}

const (
	progName   = "dyndns53"
	ipFileName = "." + progName + "-ip"
)

func main() {
	log.SetPrefix(progName + ": ")
	log.SetFlags(0)

	var recSet recordSet
	var logFn string
	flag.StringVar(&recSet.name, "name", "", "record set name (domain)")
	flag.StringVar(&recSet.rsType, "type", "A", `record set type; "A" or "AAAA"`)
	flag.Int64Var(&recSet.ttl, "ttl", 300, "TTL (time to live) in seconds")
	flag.StringVar(&recSet.hostedZoneID, "zone", "", "hosted zone id")
	flag.StringVar(&logFn, "log", "", "file name to log to (default is stdout)")
	if len(os.Args) == 1 {
		flag.Usage()
		os.Exit(1)
	}
	flag.Parse()

	recSet.name = strings.TrimSuffix(recSet.name, ".") + "." // append . if missing
	if err := recSet.validate(); err != nil {
		log.Fatal(err)
	}

	if logFn != "" {
		f, err := os.OpenFile(logFn, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			log.Fatalf("log file: %v", err)
		}
		defer f.Close()

		log.SetFlags(log.LstdFlags) // restore standard flags
		log.SetOutput(f)            // log to file
	}

	ip, err := currentIPAddress()
	if err != nil {
		log.Fatal(err)
	}

	if ip == lastIPAddress() {
		log.Printf("current IP address is %s; nothing to do", ip)
		os.Exit(0)
	}

	recSet.value = ip
	_, err = recSet.upsert()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("current IP address is %s; upsert request sent", ip)

	if err := updateLastIPAddress(ip); err != nil {
		log.Fatal(err)
	}
}

func currentIPAddress() (string, error) {
	resp, err := http.Get("http://checkip.amazonaws.com/")
	if err != nil {
		return "", fmt.Errorf("currentIPAddress: %v", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("currentIPAddress: %v", err)
	}
	ip := strings.TrimSpace(string(body))
	return ip, nil
}

func lastIPAddress() string {
	data, err := ioutil.ReadFile(ipFileName)
	if err != nil {
		return ""
	}
	return string(data)
}

func updateLastIPAddress(ip string) error {
	if err := ioutil.WriteFile(ipFileName, []byte(ip), 0644); err != nil {
		return fmt.Errorf("updateLastIPAddress: %v", err)
	}
	return nil
}

func (rs *recordSet) upsert() (*route53.ChangeResourceRecordSetsOutput, error) {
	usr, err := user.Current()
	if err != nil {
		return nil, fmt.Errorf("(*recordSet).upsert: %v", err)
	}
	credentialsPath := path.Join(usr.HomeDir, ".aws", "credentials")
	credentials := credentials.NewSharedCredentials(credentialsPath, progName)

	sess, err := session.NewSession()
	if err != nil {
		return nil, fmt.Errorf("(*recordSet).upsert: %v", err)
	}

	svc := route53.New(sess, &aws.Config{Credentials: credentials})
	params := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: []*route53.Change{
				{
					Action: aws.String("UPSERT"),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(rs.name),
						Type: aws.String(rs.rsType),
						TTL:  aws.Int64(rs.ttl),
						ResourceRecords: []*route53.ResourceRecord{
							{
								Value: aws.String(rs.value),
							},
						},
					},
				},
			},
		},
		HostedZoneId: aws.String(rs.hostedZoneID),
	}
	resp, err := svc.ChangeResourceRecordSets(params)
	if err != nil {
		return nil, fmt.Errorf("(*recordSet).upsert: %v", err)
	}
	return resp, nil
}

func (rs *recordSet) validate() error {
	if rs.name == "" {
		return fmt.Errorf("missing record set name")
	}
	if !strings.HasSuffix(rs.name, ".") {
		return fmt.Errorf(`record set name must end with a "."`)
	}
	if rs.rsType == "" {
		return fmt.Errorf("missing record set type")
	}
	if rs.rsType != "A" && rs.rsType != "AAAA" {
		return fmt.Errorf("invalid record set type: %s", rs.rsType)
	}
	if rs.ttl < 1 {
		return fmt.Errorf("invalid record set TTL: %d", rs.ttl)
	}
	if rs.hostedZoneID == "" {
		return fmt.Errorf("missing hosted zone id")
	}
	return nil
}
<commit_msg>Add support for updating many domains at once<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/user"
	"path"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/route53"
)

type (
	recordSet struct {
		names        []string
		value        string // ip
		rsType       string
		ttl          int64
		hostedZoneID string
	}

	arrayFlags []string
)

const (
	progName   = "dyndns53"
	ipFileName = "." + progName + "-ip"
)

func (i *arrayFlags) String() string {
	return strings.Join([]string(*i), " ")
}

func (i *arrayFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

func main() {
	log.SetPrefix(progName + ": ")
	log.SetFlags(0)

	var (
		recSet recordSet
		logFn  string
		names  arrayFlags
	)

	flag.Var(&names, "name", "record set names (-name domain1 -name domain2 -name domain3 ...)")
	flag.StringVar(&recSet.rsType, "type", "A", `record set type; "A" or "AAAA"`)
	flag.Int64Var(&recSet.ttl, "ttl", 300, "TTL (time to live) in seconds")
	flag.StringVar(&recSet.hostedZoneID, "zone", "", "hosted zone id")
	flag.StringVar(&logFn, "log", "", "file name to log to (default is stdout)")
	if len(os.Args) == 1 {
		flag.Usage()
		os.Exit(1)
	}
	flag.Parse()

	recSet.names = make([]string, len(names))
	for i, name := range names {
		recSet.names[i] = strings.TrimSuffix(name, ".") + "." // append . if missing
	}
	if err := recSet.validate(); err != nil {
		log.Fatal(err)
	}

	if logFn != "" {
		f, err := os.OpenFile(logFn, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			log.Fatalf("log file: %v", err)
		}
		defer f.Close()

		log.SetFlags(log.LstdFlags) // restore standard flags
		log.SetOutput(f)            // log to file
	}

	ip, err := currentIPAddress()
	if err != nil {
		log.Fatal(err)
	}

	if ip == lastIPAddress() {
		log.Printf("current IP address is %s; nothing to do", ip)
		os.Exit(0)
	}

	recSet.value = ip
	_, err = recSet.upsert()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("current IP address is %s; upsert request sent", ip)

	if err := updateLastIPAddress(ip); err != nil {
		log.Fatal(err)
	}
}

func currentIPAddress() (string, error) {
	resp, err := http.Get("http://checkip.amazonaws.com/")
	if err != nil {
		return "", fmt.Errorf("currentIPAddress: %v", err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("currentIPAddress: %v", err)
	}
	ip := strings.TrimSpace(string(body))
	return ip, nil
}

func lastIPAddress() string {
	data, err := ioutil.ReadFile(ipFileName)
	if err != nil {
		return ""
	}
	return string(data)
}

func updateLastIPAddress(ip string) error {
	if err := ioutil.WriteFile(ipFileName, []byte(ip), 0644); err != nil {
		return fmt.Errorf("updateLastIPAddress: %v", err)
	}
	return nil
}

func (rs *recordSet) upsert() (*route53.ChangeResourceRecordSetsOutput, error) {
	usr, err := user.Current()
	if err != nil {
		return nil, fmt.Errorf("(*recordSet).upsert: %v", err)
	}
	credentialsPath := path.Join(usr.HomeDir, ".aws", "credentials")
	credentials := credentials.NewSharedCredentials(credentialsPath, progName)

	sess, err := session.NewSession()
	if err != nil {
		return nil, fmt.Errorf("(*recordSet).upsert: %v", err)
	}

	svc := route53.New(sess, &aws.Config{Credentials: credentials})
	changes := make([]*route53.Change, len(rs.names))
	for i, name := range rs.names {
		changes[i] = &route53.Change{
			Action: aws.String("UPSERT"),
			ResourceRecordSet: &route53.ResourceRecordSet{
				Name: aws.String(name),
				Type: aws.String(rs.rsType),
				TTL:  aws.Int64(rs.ttl),
				ResourceRecords: []*route53.ResourceRecord{
					{
						Value: aws.String(rs.value),
					},
				},
			},
		}
	}
	params := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: changes,
		},
		HostedZoneId: aws.String(rs.hostedZoneID),
	}
	resp, err := svc.ChangeResourceRecordSets(params)
	if err != nil {
		return nil, fmt.Errorf("(*recordSet).upsert: %v", err)
	}
	return resp, nil
}

func (rs *recordSet) validate() error {
	for i, name := range rs.names {
		if name == "" {
			return fmt.Errorf("missing record set name at index %d", i)
		}
		if !strings.HasSuffix(name, ".") {
			return fmt.Errorf(`record set name at index %d must end with a "."`, i)
		}
	}
	if rs.rsType == "" {
		return fmt.Errorf("missing record set type")
	}
	if rs.rsType != "A" && rs.rsType != "AAAA" {
		return fmt.Errorf("invalid record set type: %s", rs.rsType)
	}
	if rs.ttl < 1 {
		return fmt.Errorf("invalid record set TTL: %d", rs.ttl)
	}
	if rs.hostedZoneID == "" {
		return fmt.Errorf("missing hosted zone id")
	}
	return nil
}
<|endoftext|>


<commit_before>package places

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

var (
	errInvalidByProminence = errors.New("radius must be specified when RankByProminence is used")
	errInvalidByDistance   = errors.New("when RankByDistance is specified, one or more of keyword, name, or types is required")
)

// Nearby lets you search for places within a specified area. You can refine your search request by supplying keywords or specifying the type of place you are searching for.
func (p *Service) Nearby(lat, lng float64) *NearbyCall {
	return &NearbyCall{
		service: p,
		lat:     lat,
		lng:     lng,
	}
}

type NearbyCall struct {
	service *Service

	// The latitude/longitude around which to retrieve place information
	lat, lng float64

	// A term to be matched against all content that Google has indexed for this place, including but not limited to name, type, and address, as well as customer reviews and other third-party content.
	Keyword string
	// The language code, indicating in which language the results should be returned, if possible.
	Language string
	// Restricts results to only those places within the specified price level.
	MinPrice, MaxPrice *PriceLevel
	// One or more terms to be matched against the names of places, separated with a space character. Results will be restricted to those containing the passed name values. Note that a place may have additional names associated with it, beyond its listed name. The API will try to match the passed name value against all of these names. As a result, places may be returned in the results whose listed names do not match the search term, but whose associated names do.
	Name string
	// Returns only those places that are open for business at the time the query is sent. Places that do not specify opening hours in the Google Places database will not be returned if you include this parameter in your query.
	OpenNow bool
	// Defines the distance (in meters) within which to return place results. The maximum allowed radius is 50 000 meters. Note that radius must not be included if rankby=distance is specified.
	Radius float64
	// Specifies the order in which results are listed
	RankBy RankBy
	// Restricts the results to places matching at least one of the specified types.
	Types []FeatureType
	// Restricts the search to locations that are Zagat selected businesses.
	ZagatSelected bool
	// Returns the next 20 results from a previously run search. Setting a pagetoken parameter will execute a search with the same parameters used previously — all parameters other than pagetoken will be ignored.
	PageToken string
}

func (n *NearbyCall) validate() error {
	if n.PageToken != "" {
		return nil
	}
	switch n.RankBy {
	case RankByDefault, RankByProminence:
		if n.Radius == 0 {
			return errInvalidByProminence
		}
	case RankByDistance:
		if n.Types == nil && n.Name == "" && n.Keyword == "" {
			return errInvalidByDistance
		}
	}
	return nil
}

func (n *NearbyCall) Do() (*SearchResponse, error) {
	if err := n.validate(); err != nil {
		return nil, err
	}

	searchURL := baseURL + "/nearbysearch/json?" + n.query()

	resp, err := n.service.client.Get(searchURL)
	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("bad resp %d: %s", resp.StatusCode, body)
	}

	data := &SearchResponse{}
	if err := json.Unmarshal(body, data); err != nil {
		return nil, err
	}

	if data.Status != "OK" {
		return nil, &apiError{
			Status:  data.Status,
			Message: data.ErrorMessage,
		}
	}

	return data, nil
}

func (r *NearbyCall) query() string {
	query := make(url.Values)
	query.Add("key", r.service.key)
	query.Add("location", fmt.Sprintf("%f,%f", r.lat, r.lng))

	if r.PageToken != "" {
		query.Add("pagetoken", r.PageToken)
		return query.Encode()
	}

	if r.Keyword != "" {
		query.Add("keyword", r.Keyword)
	}
	if r.Language != "" {
		query.Add("language", r.Language)
	}
	if r.MinPrice != nil {
		query.Add("minprice", fmt.Sprint(*r.MinPrice))
	}
	if r.MaxPrice != nil {
		query.Add("maxprice", fmt.Sprint(*r.MaxPrice))
	}
	if r.Name != "" {
		query.Add("name", r.Name)
	}
	if r.OpenNow {
		query.Add("opennow", fmt.Sprint(1))
	}
	if r.RankBy != RankByDistance && r.Radius > 0 {
		query.Add("radius", fmt.Sprint(r.Radius))
	}
	if r.RankBy != "" {
		query.Add("rankby", string(r.RankBy))
	}
	if r.ZagatSelected {
		query.Add("zagatselected", "")
	}

	var typeNames []string
	for _, t := range r.Types {
		typeNames = append(typeNames, string(t))
	}
	if len(typeNames) > 0 {
		query.Add("types", strings.Join(typeNames, "|"))
	}

	return query.Encode()
}

// RadarSearch returns results from up to 200 places, but with less detail than is typically returned from a Text Search or Nearby Search request.
func (p *Service) RadarSearch(radius, lat, lng float64) *RadarSearchCall {
	return &RadarSearchCall{
		service: p,
		radius:  radius,
		lat:     lat,
		lng:     lng,
	}
}

type RadarSearchCall struct {
	service *Service

	// The latitude/longitude around which to retrieve place information
	lat, lng float64
	// The distance (in meters) within which to return place results. The maximum allowed radius is 50 000 meters.
	radius float64

	// A term to be matched against all content that Google has indexed for this place, including but not limited to name, type, and address, as well as customer reviews and other third-party content.
	Keyword string
	// Restricts results to only those places within the specified price level.
	MinPrice, MaxPrice *PriceLevel
	// Returns only those places that are open for business at the time the query is sent. Places that do not specify opening hours in the Google Places database will not be returned if you include this parameter in your query.
	OpenNow bool
	// Restricts the results to places matching at least one of the specified types.
	Types []FeatureType
	// Restricts the search to locations that are Zagat selected businesses.
	ZagatSelected bool
	// Returns the next 20 results from a previously run search. Setting a pagetoken parameter will execute a search with the same parameters used previously — all parameters other than pagetoken will be ignored.
	PageToken string
}

func (r *RadarSearchCall) query() string {
	query := make(url.Values)
	query.Add("key", r.service.key)
	if r.Keyword != "" {
		query.Add("keyword", r.Keyword)
	}
	query.Add("location", fmt.Sprintf("%f,%f", r.lat, r.lng))
	if r.MinPrice != nil {
		query.Add("minprice", fmt.Sprint(*r.MinPrice))
	}
	if r.MaxPrice != nil {
		query.Add("maxprice", fmt.Sprint(*r.MaxPrice))
	}
	if r.OpenNow {
		query.Add("opennow", fmt.Sprint(1))
	}
	query.Add("radius", fmt.Sprint(r.radius))

	var typeNames []string
	for _, t := range r.Types {
		typeNames = append(typeNames, string(t))
	}
	if len(typeNames) > 0 {
		query.Add("types", strings.Join(typeNames, "|"))
	}

	if r.ZagatSelected {
		query.Add("zagatselected", "")
	}
	if r.PageToken != "" {
		query.Add("pagetoken", r.PageToken)
	}

	return query.Encode()
}

func (r *RadarSearchCall) Do() (*SearchResponse, error) {
	searchURL := baseURL + "/radarsearch/json?" + r.query()

	resp, err := r.service.client.Get(searchURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		body, _ := ioutil.ReadAll(resp.Body)
		return nil, fmt.Errorf("bad resp %d: %s", resp.StatusCode, body)
	}

	data := &SearchResponse{}
	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
		return nil, err
	}

	if data.Status != "OK" {
		return nil, &apiError{
			Status:  data.Status,
			Message: data.ErrorMessage,
		}
	}

	return data, nil
}

type SearchResponse struct {
	// A list of results matching the query
	Results []PlaceDetails `json:"results"`
	// Contains debugging information to help you track down why the request failed
	Status string `json:"status"`
	// More detailed information about the reasons behind the given status code.
	ErrorMessage string `json:"error_message,omitempty"`
	// A set of attributions about this listing which must be displayed to the user.
	HTMLAttributions []string `json:"html_attributions"`
	// A token that can be used to return up to 20 additional results. A next_page_token will not be returned if there are no additional results to display. The maximum number of results that can be returned is 60. There is a short delay between when a next_page_token is issued, and when it will become valid.
	NextPageToken string `json:"next_page_token"`
}

// RankBy specifies the order in which results are listed.
type RankBy string

const (
	// RankByDefault is an alias for RankByProminence
	RankByDefault RankBy = ""
	// RankByProminence sorts results based on their importance. Ranking will favor prominent places within the specified area. Prominence can be affected by a place's ranking in Google's index, global popularity, and other factors.
	RankByProminence RankBy = "prominence"
	// RankByDistance sorts results in ascending order by their distance from the specified location.
	RankByDistance RankBy = "distance"
)
<commit_msg>Adding the TextSearch call<commit_after>package places

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

var (
	errInvalidByProminence = errors.New("radius must be specified when RankByProminence is used")
	errInvalidByDistance   = errors.New("when RankByDistance is specified, one or more of keyword, name, or types is required")
)

// Nearby lets you search for places within a specified area. You can refine your search request by supplying keywords or specifying the type of place you are searching for.
func (p *Service) Nearby(lat, lng float64) *NearbyCall {
	return &NearbyCall{
		service: p,
		lat:     lat,
		lng:     lng,
	}
}

type NearbyCall struct {
	service *Service

	// The latitude/longitude around which to retrieve place information
	lat, lng float64

	// A term to be matched against all content that Google has indexed for this place, including but not limited to name, type, and address, as well as customer reviews and other third-party content.
	Keyword string
	// The language code, indicating in which language the results should be returned, if possible.
	Language string
	// Restricts results to only those places within the specified price level.
	MinPrice, MaxPrice *PriceLevel
	// One or more terms to be matched against the names of places, separated with a space character. Results will be restricted to those containing the passed name values. Note that a place may have additional names associated with it, beyond its listed name. The API will try to match the passed name value against all of these names. As a result, places may be returned in the results whose listed names do not match the search term, but whose associated names do.
	Name string
	// Returns only those places that are open for business at the time the query is sent. Places that do not specify opening hours in the Google Places database will not be returned if you include this parameter in your query.
	OpenNow bool
	// Defines the distance (in meters) within which to return place results. The maximum allowed radius is 50 000 meters. Note that radius must not be included if rankby=distance is specified.
	Radius float64
	// Specifies the order in which results are listed
	RankBy RankBy
	// Restricts the results to places matching at least one of the specified types.
	Types []FeatureType
	// Restricts the search to locations that are Zagat selected businesses.
	ZagatSelected bool
	// Returns the next 20 results from a previously run search. Setting a pagetoken parameter will execute a search with the same parameters used previously — all parameters other than pagetoken will be ignored.
	PageToken string
}

func (n *NearbyCall) validate() error {
	if n.PageToken != "" {
		return nil
	}
	switch n.RankBy {
	case RankByDefault, RankByProminence:
		if n.Radius == 0 {
			return errInvalidByProminence
		}
	case RankByDistance:
		if n.Types == nil && n.Name == "" && n.Keyword == "" {
			return errInvalidByDistance
		}
	}
	return nil
}

func (n *NearbyCall) Do() (*SearchResponse, error) {
	if err := n.validate(); err != nil {
		return nil, err
	}

	searchURL := baseURL + "/nearbysearch/json?" + n.query()

	resp, err := n.service.client.Get(searchURL)
	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("bad resp %d: %s", resp.StatusCode, body)
	}

	data := &SearchResponse{}
	if err := json.Unmarshal(body, data); err != nil {
		return nil, err
	}

	if data.Status != "OK" {
		return nil, &apiError{
			Status:  data.Status,
			Message: data.ErrorMessage,
		}
	}

	return data, nil
}

func (r *NearbyCall) query() string {
	query := make(url.Values)
	query.Add("key", r.service.key)
	query.Add("location", fmt.Sprintf("%f,%f", r.lat, r.lng))

	if r.PageToken != "" {
		query.Add("pagetoken", r.PageToken)
		return query.Encode()
	}

	if r.Keyword != "" {
		query.Add("keyword", r.Keyword)
	}
	if r.Language != "" {
		query.Add("language", r.Language)
	}
	if r.MinPrice != nil {
		query.Add("minprice", fmt.Sprint(*r.MinPrice))
	}
	if r.MaxPrice != nil {
		query.Add("maxprice", fmt.Sprint(*r.MaxPrice))
	}
	if r.Name != "" {
		query.Add("name", r.Name)
	}
	if r.OpenNow {
		query.Add("opennow", fmt.Sprint(1))
	}
	if r.RankBy != RankByDistance && r.Radius > 0 {
		query.Add("radius", fmt.Sprint(r.Radius))
	}
	if r.RankBy != "" {
		query.Add("rankby", string(r.RankBy))
	}
	if r.ZagatSelected {
		query.Add("zagatselected", "")
	}

	var typeNames []string
	for _, t := range r.Types {
		typeNames = append(typeNames, string(t))
	}
	if len(typeNames) > 0 {
		query.Add("types", strings.Join(typeNames, "|"))
	}

	return query.Encode()
}

// The Text Search Service is a web service that returns information about a set of places based on a string.
func (p *Service) TextSearch(query string) *TextSearchCall {
	return &TextSearchCall{
		service:  p,
		queryStr: query,
	}
}

type TextSearchCall struct {
	service *Service

	// The text string on which to search, for example: "restaurant". The Google Places service will return candidate matches based on this string and order the results based on their perceived relevance.
	queryStr string

	// The latitude/longitude around which to retrieve place information
	lat, lng float64
	// The language code, indicating in which language the results should be returned, if possible.
	Language string
	// Restricts results to only those places within the specified price level.
	MinPrice, MaxPrice *PriceLevel
	// Returns only those places that are open for business at the time the query is sent. Places that do not specify opening hours in the Google Places database will not be returned if you include this parameter in your query.
	OpenNow bool
	// Defines the distance (in meters) within which to return place results. The maximum allowed radius is 50 000 meters. Note that radius must not be included if rankby=distance is specified.
	Radius float64
	// Restricts the results to places matching at least one of the specified types.
	Types []FeatureType
	// Restricts the search to locations that are Zagat selected businesses.
	ZagatSelected bool
	// Returns the next 20 results from a previously run search. Setting a pagetoken parameter will execute a search with the same parameters used previously — all parameters other than pagetoken will be ignored.
	PageToken string
}

func (t *TextSearchCall) validate() error {
	if t.PageToken != "" {
		return nil
	}

	return nil
}

func (t *TextSearchCall) Do() (*SearchResponse, error) {
	if err := t.validate(); err != nil {
		return nil, err
	}

	searchURL := baseURL + "/textsearch/json?" + t.query()
	resp, err := t.service.client.Get(searchURL)
	if err != nil {
		return nil, err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("bad resp %d: %s", resp.StatusCode, body)
	}

	data := &SearchResponse{}
	if err := json.Unmarshal(body, data); err != nil {
		return nil, err
	}

	if data.Status != "OK" {
		return nil, &apiError{
			Status:  data.Status,
			Message: data.ErrorMessage,
		}
	}

	return data, nil
}

func (t *TextSearchCall) query() string {
	query := make(url.Values)
	query.Add("key", t.service.key)

	if t.PageToken != "" {
		query.Add("pagetoken", t.PageToken)
		return query.Encode()
	}

	if t.lat > 0 && t.lng > 0 {
		query.Add("location", fmt.Sprintf("%f,%f", t.lat, t.lng))
	}
	if t.Language != "" {
		query.Add("language", t.Language)
	}
	if t.queryStr != "" {
		query.Add("query", t.queryStr)
	}
	if t.MinPrice != nil {
		query.Add("minprice", fmt.Sprint(*t.MinPrice))
	}
	if t.MaxPrice != nil {
		query.Add("maxprice", fmt.Sprint(*t.MaxPrice))
	}
	if t.OpenNow {
		query.Add("opennow", fmt.Sprint(1))
	}
	if t.Radius > 0 {
		query.Add("radius", fmt.Sprint(t.Radius))
	}
	if t.ZagatSelected {
		query.Add("zagatselected", "")
	}

	var typeNames []string
	for _, t := range t.Types {
		typeNames = append(typeNames, string(t))
	}
	if len(typeNames) > 0 {
		query.Add("types", strings.Join(typeNames, "|"))
	}

	return query.Encode()
}

// RadarSearch returns results from up to 200 places, but with less detail than is typically returned from a Text Search or Nearby Search request.
func (p *Service) RadarSearch(radius, lat, lng float64) *RadarSearchCall {
	return &RadarSearchCall{
		service: p,
		radius:  radius,
		lat:     lat,
		lng:     lng,
	}
}

type RadarSearchCall struct {
	service *Service

	// The latitude/longitude around which to retrieve place information
	lat, lng float64
	// The distance (in meters) within which to return place results. The maximum allowed radius is 50 000 meters.
	radius float64

	// A term to be matched against all content that Google has indexed for this place, including but not limited to name, type, and address, as well as customer reviews and other third-party content.
	Keyword string
	// Restricts results to only those places within the specified price level.
	MinPrice, MaxPrice *PriceLevel
	// Returns only those places that are open for business at the time the query is sent. Places that do not specify opening hours in the Google Places database will not be returned if you include this parameter in your query.
	OpenNow bool
	// Restricts the results to places matching at least one of the specified types.
	Types []FeatureType
	// Restricts the search to locations that are Zagat selected businesses.
	ZagatSelected bool
	// Returns the next 20 results from a previously run search. Setting a pagetoken parameter will execute a search with the same parameters used previously — all parameters other than pagetoken will be ignored.
	PageToken string
}

func (r *RadarSearchCall) query() string {
	query := make(url.Values)
	query.Add("key", r.service.key)
	if r.Keyword != "" {
		query.Add("keyword", r.Keyword)
	}
	query.Add("location", fmt.Sprintf("%f,%f", r.lat, r.lng))
	if r.MinPrice != nil {
		query.Add("minprice", fmt.Sprint(*r.MinPrice))
	}
	if r.MaxPrice != nil {
		query.Add("maxprice", fmt.Sprint(*r.MaxPrice))
	}
	if r.OpenNow {
		query.Add("opennow", fmt.Sprint(1))
	}
	query.Add("radius", fmt.Sprint(r.radius))

	var typeNames []string
	for _, t := range r.Types {
		typeNames = append(typeNames, string(t))
	}
	if len(typeNames) > 0 {
		query.Add("types", strings.Join(typeNames, "|"))
	}

	if r.ZagatSelected {
		query.Add("zagatselected", "")
	}
	if r.PageToken != "" {
		query.Add("pagetoken", r.PageToken)
	}

	return query.Encode()
}

func (r *RadarSearchCall) Do() (*SearchResponse, error) {
	searchURL := baseURL + "/radarsearch/json?" + r.query()

	resp, err := r.service.client.Get(searchURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		body, _ := ioutil.ReadAll(resp.Body)
		return nil, fmt.Errorf("bad resp %d: %s", resp.StatusCode, body)
	}

	data := &SearchResponse{}
	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
		return nil, err
	}

	if data.Status != "OK" {
		return nil, &apiError{
			Status:  data.Status,
			Message: data.ErrorMessage,
		}
	}

	return data, nil
}

type SearchResponse struct {
	// A list of results matching the query
	Results []PlaceDetails `json:"results"`
	// Contains debugging information to help you track down why the request failed
	Status string `json:"status"`
	// More detailed information about the reasons behind the given status code.
	ErrorMessage string `json:"error_message,omitempty"`
	// A set of attributions about this listing which must be displayed to the user.
	HTMLAttributions []string `json:"html_attributions"`
	// A token that can be used to return up to 20 additional results. A next_page_token will not be returned if there are no additional results to display. The maximum number of results that can be returned is 60. There is a short delay between when a next_page_token is issued, and when it will become valid.
	NextPageToken string `json:"next_page_token"`
}

// RankBy specifies the order in which results are listed.
type RankBy string

const (
	// RankByDefault is an alias for RankByProminence
	RankByDefault RankBy = ""
	// RankByProminence sorts results based on their importance. Ranking will favor prominent places within the specified area. Prominence can be affected by a place's ranking in Google's index, global popularity, and other factors.
	RankByProminence RankBy = "prominence"
	// RankByDistance sorts results in ascending order by their distance from the specified location.
	RankByDistance RankBy = "distance"
)
<|endoftext|>


<commit_before>// Rails-configd - an online rails configuration generator using etcd data
//
// Standard usage:
//   (inside your Rails app)
//   $ rails-configd -etcd http://localhost:4001 -etcd-dir /rails/production -env production -renderer yaml -reloader touch
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"strings"

	"golang.org/x/net/context"

	"github.com/coreos/etcd/client"
	"github.com/rubenfonseca/rails-configd/src"
)

var usageMessage = `rails-configd [%s]
This is a tool for watching over etcd tree, create config files for Rails, and restart the Rails processes.

Usage: %s [options]

The following options are recognized:
`

func usage() {
	fmt.Fprintf(os.Stderr, usageMessage, releaseVersion, os.Args[0])
	flag.PrintDefaults()
	os.Exit(2)
}

func loop(receiverChannel chan *client.Response, env src.Env) {
	for response := range receiverChannel {
		key := env.NakedKey(response.Node.Key, *env.EtcdDir)
		parts := strings.Split(key, "/")
		env.UpdateData(parts, response.Node.Value, response.Action, env.Data)

		log.Printf("[CHANGE]: %s %s %s", response.Action, key, response.Node.Value)

		env.Cycle()
	}
}

func main() {
	env := src.Env{}
	env.Data = make(map[string]interface{})

	env.Etcd = flag.String("etcd", "http://localhost:4001", "etcd address location")
	env.EtcdDir = flag.String("etcd-dir", "/rails_app01", "etcd directory that contains the configurations")

	rendererPtr := flag.String("renderer", "yaml", "The renderer to use when outputing the configs")
	reloaderPtr := flag.String("reloader", "touch", "The strategy to reload the Rails app")

	src.RegisterRendererFlags()
	src.RegisterReloaderFlags()

	flag.Usage = usage
	flag.Parse()

	// renderer
	renderer, err := src.OpenRenderer(*rendererPtr)
	if err != nil {
		panic(err)
	}
	env.Renderer = renderer

	// reloader
	env.Reloader, err = src.OpenReloader(*reloaderPtr)
	if err != nil {
		panic(err)
	}

	// main app context
	ctx, cancel := context.WithCancel(context.Background())

	// etcd
	etcdClientConfig := client.Config{Endpoints: []string{*env.Etcd}}
	etcdClient, err := client.New(etcdClientConfig)
	if err != nil {
		log.Fatal("Cannot connect to etcd machines, pleace check --etcd")
	}
	etcdKeyClient := client.NewKeysAPI(etcdClient)

	etcdGetOptions := &client.GetOptions{Recursive: true, Sort: false}
	etcdResponse, err := etcdKeyClient.Get(ctx, *env.EtcdDir, etcdGetOptions)
	if err != nil {
		panic(err)
	}
	if !etcdResponse.Node.Dir {
		panic("etc-dir should be a directory")
	}
	env.BuildData(*etcdResponse.Node, *env.EtcdDir, env.Data)
	env.Cycle()

	// watcher
	log.Printf("[MAIN] Waiting for changes from etcd @ %s", *env.EtcdDir)
	etcdWatcherOptions := &client.WatcherOptions{AfterIndex: 0, Recursive: true}
	etcdWatcher := etcdKeyClient.Watcher(*env.EtcdDir, etcdWatcherOptions)

	watcher := src.Watcher{EtcdWatcher: etcdWatcher}
	receiverChannel := watcher.Loop(ctx)

	// signals
	osSignal := make(chan os.Signal)
	signal.Notify(osSignal, os.Interrupt)
	go func() {
		for _ = range osSignal {
			log.Print("Interrupt received, finishing")
			cancel()
		}
	}()

	loop(receiverChannel, env)
}
<commit_msg>Refactored flag usage.<commit_after>// Rails-configd - an online rails configuration generator using etcd data
//
// Standard usage:
//   (inside your Rails app)
//   $ rails-configd -etcd http://localhost:4001 -etcd-dir /rails/production -env production -renderer yaml -reloader touch
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"strings"

	"golang.org/x/net/context"

	"github.com/coreos/etcd/client"
	"github.com/rubenfonseca/rails-configd/src"
)

var (
	etcdFlag     = flag.String("etcd", "http://localhost:4001", "etcd address location")
	etcdDirFlag  = flag.String("etcd-dir", "/rails_app01", "etcd directory that contains the configurations")
	rendererFlag = flag.String("renderer", "yaml", "The renderer to use when outputing the configs")
	reloaderFlag = flag.String("reloader", "touch", "The strategy to reload the Rails app")
)

const usageMessage = `rails-configd [%s]
This is a tool for watching over etcd tree, create config files for Rails, and restart the Rails processes.

Usage: %s [options]

The following options are recognized:
`

func printHelp() {
	fmt.Fprintf(os.Stderr, usageMessage, releaseVersion, os.Args[0])
	flag.PrintDefaults()
}

func loop(receiverChannel chan *client.Response, env src.Env) {
	for response := range receiverChannel {
		key := env.NakedKey(response.Node.Key, *env.EtcdDir)
		parts := strings.Split(key, "/")
		env.UpdateData(parts, response.Node.Value, response.Action, env.Data)

		log.Printf("[CHANGE]: %s %s %s", response.Action, key, response.Node.Value)

		env.Cycle()
	}
}

func main() {
	var err error
	env := src.Env{Etcd: etcdFlag, EtcdDir: etcdDirFlag, Data: make(map[string]interface{})}

	src.RegisterRendererFlags()
	src.RegisterReloaderFlags()

	flag.Usage = printHelp
	flag.Parse()

	// renderer
	env.Renderer, err = src.OpenRenderer(*rendererFlag)
	if err != nil {
		panic(err)
	}

	// reloader
	env.Reloader, err = src.OpenReloader(*reloaderFlag)
	if err != nil {
		panic(err)
	}

	// main app context
	ctx, cancel := context.WithCancel(context.Background())

	// etcd
	etcdClientConfig := client.Config{Endpoints: []string{*env.Etcd}}
	etcdClient, err := client.New(etcdClientConfig)
	if err != nil {
		log.Fatal("Cannot connect to etcd machines, pleace check --etcd")
	}
	etcdKeyClient := client.NewKeysAPI(etcdClient)

	etcdGetOptions := &client.GetOptions{Recursive: true, Sort: false}
	etcdResponse, err := etcdKeyClient.Get(ctx, *env.EtcdDir, etcdGetOptions)
	if err != nil {
		panic(err)
	}
	if !etcdResponse.Node.Dir {
		panic("etc-dir should be a directory")
	}
	env.BuildData(*etcdResponse.Node, *env.EtcdDir, env.Data)
	env.Cycle()

	// watcher
	log.Printf("[MAIN] Waiting for changes from etcd @ %s", *env.EtcdDir)
	etcdWatcherOptions := &client.WatcherOptions{AfterIndex: 0, Recursive: true}
	etcdWatcher := etcdKeyClient.Watcher(*env.EtcdDir, etcdWatcherOptions)

	watcher := src.Watcher{EtcdWatcher: etcdWatcher}
	receiverChannel := watcher.Loop(ctx)

	// signals
	osSignal := make(chan os.Signal)
	signal.Notify(osSignal, os.Interrupt)
	go func() {
		for _ = range osSignal {
			log.Print("Interrupt received, finishing")
			cancel()
		}
	}()

	loop(receiverChannel, env)
}
<|endoftext|>


<commit_before>package player

import (
	"errors"
	"strings"
	"net"
	"log"
	"io/ioutil"
)

var  Exited = errors.New("Player exited.")
var UnknownMode = errors.New("No such mode exists.")

const (
	SplashMode = iota
	LoginUsernameMode
	LoginPasswordMode
	NormalMode
)

type Command struct {
	Name string
	Help string
	Aliases []string
	Func func(*Player, string) (string, error)
}

type Mode struct {
	Id int
	Name string
	Desc string
	DescFile string
	Cmds []*Command
}

func (m *Mode) Render() string {
	if m.Desc == "" && m.DescFile != "" {
		raw, err := ioutil.ReadFile("splash.txt")
		if err != nil {
			log.Printf("failed to read splash.txt: %v", err)
			return m.Desc
		}
		m.Desc = string(raw)
	}
	return m.Desc
}

var modes map[int]*Mode

func LoadModes() {
	modes = map[int]*Mode{}
	modes[SplashMode] = &Mode{Id: SplashMode, Name: "Splash", DescFile: "splash.txt"}
	modes[LoginUsernameMode] = &Mode{Id: LoginUsernameMode, Name: "LoginUsername", DescFile: "login_username.txt"}
	modes[LoginPasswordMode] = &Mode{Id: LoginPasswordMode, Name: "LoginPassword", DescFile: "login_password.txt"}

	splashCmds := make([]*Command, 0)
	loginCmd := &Command{
		Name: "login",
		Aliases: []string{"l"},
		Func: func(p *Player, cmd string) (string, error) {

			return "test test test test", nil
		},
	}
	splashCmds = append(splashCmds, loginCmd)

	modes[SplashMode].Cmds = splashCmds
}

func GetMode(mode int) (*Mode, error) {
	if modes[mode] == nil {
		return &Mode{}, UnknownMode
	}
	return modes[mode], nil
}

type Player struct {
	Conn net.Conn
	Created bool
	Name string
	UUID string
	Mode *Mode
	HP int
}

func (p *Player) HandleMessage(msg string) (string, error) {
	log.Printf("Msg Received (len %v): '%v'", len(msg), msg)
	if msg == "exit" {
		return "See you next time.", Exited
	}
	words := strings.Split(strings.ToLower(msg), " ")
	if len(words) > 0 {
		first := words[0]
		log.Printf("Trying to match %v", first)
		for _, cmd := range p.Mode.Cmds {
			log.Printf("Trying to match %v to %v", first, cmd.Name)
			if first == cmd.Name {
				return cmd.Func(p, msg)
			}
			for _, alias := range cmd.Aliases {
				log.Printf("Trying to match %v to %v", first, alias)
				if first == alias {
					return cmd.Func(p, msg)
				}
			}
		}
	}
	return "", nil
}

func (p *Player) Splash() string {
	mode, err := GetMode(SplashMode)
	p.Mode = mode
	if err != nil {
		log.Printf("error retrieving mode %v: %v", SplashMode, err)
	}
	return mode.Render()
}
<commit_msg>progress<commit_after>package player

import (
	"errors"
	"strings"
	"net"
	"log"
	"io/ioutil"
)

var  Exited = errors.New("Player exited.")
var UnknownMode = errors.New("No such mode exists.")

const (
	SplashMode = iota
	LoginUsernameMode
	LoginPasswordMode
	NormalMode
)

type Command struct {
	Name string
	Help string
	Aliases []string
	Func func(*Player, string) (string, error)
}

type Mode struct {
	Id int
	Name string
	Desc string
	DescFile string
	Cmds []*Command
}

func (m *Mode) Render() string {
	if m.Desc == "" && m.DescFile != "" {
		raw, err := ioutil.ReadFile("splash.txt")
		if err != nil {
			log.Printf("failed to read splash.txt: %v", err)
			return m.Desc
		}
		m.Desc = string(raw)
	}
	return m.Desc
}

var modes map[int]*Mode

func LoadModes() {
	modes = map[int]*Mode{}
	modes[SplashMode] = &Mode{Id: SplashMode, Name: "Splash", DescFile: "splash.txt"}
	modes[LoginUsernameMode] = &Mode{Id: LoginUsernameMode, Name: "LoginUsername", DescFile: "login_username.txt"}
	modes[LoginPasswordMode] = &Mode{Id: LoginPasswordMode, Name: "LoginPassword", DescFile: "login_password.txt"}

	splashCmds := make([]*Command, 0)
	loginCmd := &Command{
		Name: "login",
		Aliases: []string{"l"},
		Func: func(p *Player, cmd string) (string, error) {
			p.Mode = MustGetMode(LoginUsernameMode)
			return p.Mode.Render(), nil
		},
	}
	splashCmds = append(splashCmds, loginCmd)

	modes[SplashMode].Cmds = splashCmds
}

func GetMode(mode int) (*Mode, error) {
	if modes[mode] == nil {
		return &Mode{}, UnknownMode
	}
	return modes[mode], nil
}

func MustGetMode(mode int) *Mode {
	m, err := GetMode(mode)
	if err != nil {
		panic(err)
	}
	return m
}

type Player struct {
	Conn net.Conn
	Created bool
	Name string
	UUID string
	Mode *Mode
	HP int
}

func (p *Player) HandleMessage(msg string) (string, error) {
	log.Printf("Msg Received (len %v): '%v'", len(msg), msg)
	if msg == "exit" {
		return "See you next time.", Exited
	}
	words := strings.Split(strings.ToLower(msg), " ")
	if len(words) > 0 {
		first := words[0]
		log.Printf("Trying to match %v", first)
		for _, cmd := range p.Mode.Cmds {
			log.Printf("Trying to match %v to %v", first, cmd.Name)
			if first == cmd.Name {
				return cmd.Func(p, msg)
			}
			for _, alias := range cmd.Aliases {
				log.Printf("Trying to match %v to %v", first, alias)
				if first == alias {
					return cmd.Func(p, msg)
				}
			}
		}
	}
	return "", nil
}

func (p *Player) Splash() string {
	p.Mode = MustGetMode(SplashMode)
	return p.Mode.Render()
}
<|endoftext|>


<commit_before>package raft

import (
	"fmt"
	"io"
	"log"
	"time"
)

// These are the versions of the protocol (which includes RPC messages as
// well as Raft-specific log entries) that this server can _understand_. Use
// the ProtocolVersion member of the Config object to control the version of
// the protocol to use when _speaking_ to other servers. This is not currently
// written into snapshots so they are unversioned. Note that depending on the
// protocol version being spoken, some otherwise understood RPC messages may be
// refused. See isVersionCompatible for details of this logic.
//
// There are notes about the upgrade path in the description of the versions
// below. If you are starting a fresh cluster then there's no reason not to
// jump right to the latest protocol version. If you need to interoperate with
// older, unversioned Raft servers you'll need to drive the cluster through the
// different versions in order.
//
// The version details are complicated, but here's a summary of what's required
// to get from an unversioned cluster to version 2:
//
// 1. In version N of your app that starts using the new Raft library with
//    versioning, set ProtocolVersion to 1.
// 2. Make version N+1 of your app require version N as a prerequisite (all
//    servers must be upgraded). For version N+1 of your app set ProtocolVersion
//    to 2.
// 3. Similarly, make version N+2 of your app require version N+1 as a
//    prerequisite. For version N+2 of your app, set ProtocolVersion to 3.
//
// During this upgrade, older cluster members will still have Server IDs equal
// to their network addresses. To upgrade an older member and give it an ID, it
// needs to leave the cluster and re-enter:
//
// 1. Remove the server from the cluster with RemoveServer, using its network
//    address as its ServerID.
// 2. Update the server's config to a better ID (restarting the server).
// 3. Add the server back to the cluster with AddVoter, using its new ID.
//
// You can do this during the rolling upgrade from N+1 to N+2 of your app, or
// as a rolling change at any time after the upgrade.
//
// Version History
//
// 0: Original Raft library before versioning was added. Servers running this
//    version of the Raft library use AddPeerDeprecated/RemovePeerDeprecated
//    for all configuration changes, and have no support for LogConfiguration.
// 1: First versioned protocol, used to interoperate with old servers, and begin
//    the migration path to newer versions of the protocol. Under this version
//    all configuration changes are propagated using the now-deprecated
//    RemovePeerDeprecated Raft log entry. This means that server IDs are always
//    set to be the same as the server addresses (since the old log entry type
//    cannot transmit an ID), and only AddPeer/RemovePeer APIs are supported.
//    Servers running this version of the protocol can understand the new
//    LogConfiguration Raft log entry but will never generate one so they can
//    remain compatible with version 0 Raft servers in the cluster.
// 2: Transitional protocol used when migrating an existing cluster to the new
//    server ID system. Server IDs are still set to be the same as server
//    addresses, but all configuration changes are propagated using the new
//    LogConfiguration Raft log entry type, which can carry full ID information.
//    This version supports the old AddPeer/RemovePeer APIs as well as the new
//    ID-based AddVoter/RemoveServer APIs which should be used when adding
//    version 3 servers to the cluster later. This version sheds all
//    interoperability with version 0 servers, but can interoperate with newer
//    Raft servers running with protocol version 1 since they can understand the
//    new LogConfiguration Raft log entry, and this version can still understand
//    their RemovePeerDeprecated Raft log entries. We need this protocol version
//    as an intermediate step between 1 and 3 so that servers will propagate the
//    ID information that will come from newly-added (or -rolled) servers using
//    protocol version 3, but since they are still using their address-based IDs
//    from the previous step they will still be able to track commitments and
//    their own voting status properly. If we skipped this step, servers would
//    be started with their new IDs, but they wouldn't see themselves in the old
//    address-based configuration, so none of the servers would think they had a
//    vote.
// 3: Protocol adding full support for server IDs and new ID-based server APIs
//    (AddVoter, AddNonvoter, etc.), old AddPeer/RemovePeer APIs are no longer
//    supported. Version 2 servers should be swapped out by removing them from
//    the cluster one-by-one and re-adding them with updated configuration for
//    this protocol version, along with their server ID. The remove/add cycle
//    is required to populate their server ID. Note that removing must be done
//    by ID, which will be the old server's address.
const (
	ProtocolVersionMin = 0
	ProtocolVersionMax = 3
)

// Config provides any necessary configuration to
// the Raft server
type Config struct {
	// ProtocolVersion allows a Raft server to inter-operate with older
	// Raft servers running an older version of the code. This is used to
	// version the wire protocol as well as Raft-specific log entries that
	// the server uses when _speaking_ to other servers. There is currently
	// no auto-negotiation of versions so all servers must be manually
	// configured with compatible versions. See ProtocolVersionMin and
	// ProtocolVersionMax for the versions of the protocol that this server
	// can _understand_.
	ProtocolVersion int

	// HeartbeatTimeout specifies the time in follower state without
	// a leader before we attempt an election.
	HeartbeatTimeout time.Duration

	// ElectionTimeout specifies the time in candidate state without
	// a leader before we attempt an election.
	ElectionTimeout time.Duration

	// CommitTimeout controls the time without an Apply() operation
	// before we heartbeat to ensure a timely commit. Due to random
	// staggering, may be delayed as much as 2x this value.
	CommitTimeout time.Duration

	// MaxAppendEntries controls the maximum number of append entries
	// to send at once. We want to strike a balance between efficiency
	// and avoiding waste if the follower is going to reject because of
	// an inconsistent log.
	MaxAppendEntries int

	// If we are a member of a cluster, and RemovePeer is invoked for the
	// local node, then we forget all peers and transition into the follower state.
	// If ShutdownOnRemove is is set, we additional shutdown Raft. Otherwise,
	// we can become a leader of a cluster containing only this node.
	ShutdownOnRemove bool

	// TrailingLogs controls how many logs we leave after a snapshot. This is
	// used so that we can quickly replay logs on a follower instead of being
	// forced to send an entire snapshot.
	TrailingLogs uint64

	// SnapshotInterval controls how often we check if we should perform a snapshot.
	// We randomly stagger between this value and 2x this value to avoid the entire
	// cluster from performing a snapshot at once.
	SnapshotInterval time.Duration

	// SnapshotThreshold controls how many outstanding logs there must be before
	// we perform a snapshot. This is to prevent excessive snapshots when we can
	// just replay a small set of logs.
	SnapshotThreshold uint64

	// LeaderLeaseTimeout is used to control how long the "lease" lasts
	// for being the leader without being able to contact a quorum
	// of nodes. If we reach this interval without contact, we will
	// step down as leader.
	LeaderLeaseTimeout time.Duration

	// StartAsLeader forces Raft to start in the leader state. This should
	// never be used except for testing purposes, as it can cause a split-brain.
	StartAsLeader bool

	// The unique ID for this server across all time. When running with
	// ProtocolVersion < 3, you must set this to be the same as the network
	// address of your transport.
	LocalID ServerID

	// NotifyCh is used to provide a channel that will be notified of leadership
	// changes. Raft will block writing to this channel, so it should either be
	// buffered or aggressively consumed.
	NotifyCh chan<- bool

	// LogOutput is used as a sink for logs, unless Logger is specified.
	// Defaults to os.Stderr.
	LogOutput io.Writer

	// Logger is a user-provided logger. If nil, a logger writing to LogOutput
	// is used.
	Logger *log.Logger
}

// DefaultConfig returns a Config with usable defaults.
func DefaultConfig() *Config {
	return &Config{
		ProtocolVersion:    ProtocolVersionMax,
		HeartbeatTimeout:   1000 * time.Millisecond,
		ElectionTimeout:    1000 * time.Millisecond,
		CommitTimeout:      50 * time.Millisecond,
		MaxAppendEntries:   64,
		ShutdownOnRemove:   true,
		TrailingLogs:       10240,
		SnapshotInterval:   120 * time.Second,
		SnapshotThreshold:  8192,
		LeaderLeaseTimeout: 500 * time.Millisecond,
	}
}

// ValidateConfig is used to validate a sane configuration
func ValidateConfig(config *Config) error {
	// We don't actually support running as 0 in the library any more, but
	// we do understand it.
	protocolMin := ProtocolVersionMin
	if protocolMin == 0 {
		protocolMin = 1
	}
	if config.ProtocolVersion < protocolMin ||
		config.ProtocolVersion > ProtocolVersionMax {
		return fmt.Errorf("Protocol version %d must be >= %d and <= %d",
			config.ProtocolVersion, protocolMin, ProtocolVersionMax)
	}
	if len(config.LocalID) == 0 {
		return fmt.Errorf("LocalID cannot be empty")
	}
	if config.HeartbeatTimeout < 5*time.Millisecond {
		return fmt.Errorf("Heartbeat timeout is too low")
	}
	if config.ElectionTimeout < 5*time.Millisecond {
		return fmt.Errorf("Election timeout is too low")
	}
	if config.CommitTimeout < time.Millisecond {
		return fmt.Errorf("Commit timeout is too low")
	}
	if config.MaxAppendEntries <= 0 {
		return fmt.Errorf("MaxAppendEntries must be positive")
	}
	if config.MaxAppendEntries > 1024 {
		return fmt.Errorf("MaxAppendEntries is too large")
	}
	if config.SnapshotInterval < 5*time.Millisecond {
		return fmt.Errorf("Snapshot interval is too low")
	}
	if config.LeaderLeaseTimeout < 5*time.Millisecond {
		return fmt.Errorf("Leader lease timeout is too low")
	}
	if config.LeaderLeaseTimeout > config.HeartbeatTimeout {
		return fmt.Errorf("Leader lease timeout cannot be larger than heartbeat timeout")
	}
	if config.ElectionTimeout < config.HeartbeatTimeout {
		return fmt.Errorf("Election timeout must be equal or greater than Heartbeat Timeout")
	}
	return nil
}
<commit_msg>Cleans up verbiage in config.go comments.<commit_after>package raft

import (
	"fmt"
	"io"
	"log"
	"time"
)

// These are the versions of the protocol (which includes RPC messages as
// well as Raft-specific log entries) that this server can _understand_. Use
// the ProtocolVersion member of the Config object to control the version of
// the protocol to use when _speaking_ to other servers. This is not currently
// written into snapshots so they are unversioned. Note that depending on the
// protocol version being spoken, some otherwise understood RPC messages may be
// refused. See isVersionCompatible for details of this logic.
//
// There are notes about the upgrade path in the description of the versions
// below. If you are starting a fresh cluster then there's no reason not to
// jump right to the latest protocol version. If you need to interoperate with
// older, version 0 Raft servers you'll need to drive the cluster through the
// different versions in order.
//
// The version details are complicated, but here's a summary of what's required
// to get from a version 0 cluster to version 3:
//
// 1. In version N of your app that starts using the new Raft library with
//    versioning, set ProtocolVersion to 1.
// 2. Make version N+1 of your app require version N as a prerequisite (all
//    servers must be upgraded). For version N+1 of your app set ProtocolVersion
//    to 2.
// 3. Similarly, make version N+2 of your app require version N+1 as a
//    prerequisite. For version N+2 of your app, set ProtocolVersion to 3.
//
// During this upgrade, older cluster members will still have Server IDs equal
// to their network addresses. To upgrade an older member and give it an ID, it
// needs to leave the cluster and re-enter:
//
// 1. Remove the server from the cluster with RemoveServer, using its network
//    address as its ServerID.
// 2. Update the server's config to a better ID (restarting the server).
// 3. Add the server back to the cluster with AddVoter, using its new ID.
//
// You can do this during the rolling upgrade from N+1 to N+2 of your app, or
// as a rolling change at any time after the upgrade.
//
// Version History
//
// 0: Original Raft library before versioning was added. Servers running this
//    version of the Raft library use AddPeerDeprecated/RemovePeerDeprecated
//    for all configuration changes, and have no support for LogConfiguration.
// 1: First versioned protocol, used to interoperate with old servers, and begin
//    the migration path to newer versions of the protocol. Under this version
//    all configuration changes are propagated using the now-deprecated
//    RemovePeerDeprecated Raft log entry. This means that server IDs are always
//    set to be the same as the server addresses (since the old log entry type
//    cannot transmit an ID), and only AddPeer/RemovePeer APIs are supported.
//    Servers running this version of the protocol can understand the new
//    LogConfiguration Raft log entry but will never generate one so they can
//    remain compatible with version 0 Raft servers in the cluster.
// 2: Transitional protocol used when migrating an existing cluster to the new
//    server ID system. Server IDs are still set to be the same as server
//    addresses, but all configuration changes are propagated using the new
//    LogConfiguration Raft log entry type, which can carry full ID information.
//    This version supports the old AddPeer/RemovePeer APIs as well as the new
//    ID-based AddVoter/RemoveServer APIs which should be used when adding
//    version 3 servers to the cluster later. This version sheds all
//    interoperability with version 0 servers, but can interoperate with newer
//    Raft servers running with protocol version 1 since they can understand the
//    new LogConfiguration Raft log entry, and this version can still understand
//    their RemovePeerDeprecated Raft log entries. We need this protocol version
//    as an intermediate step between 1 and 3 so that servers will propagate the
//    ID information that will come from newly-added (or -rolled) servers using
//    protocol version 3, but since they are still using their address-based IDs
//    from the previous step they will still be able to track commitments and
//    their own voting status properly. If we skipped this step, servers would
//    be started with their new IDs, but they wouldn't see themselves in the old
//    address-based configuration, so none of the servers would think they had a
//    vote.
// 3: Protocol adding full support for server IDs and new ID-based server APIs
//    (AddVoter, AddNonvoter, etc.), old AddPeer/RemovePeer APIs are no longer
//    supported. Version 2 servers should be swapped out by removing them from
//    the cluster one-by-one and re-adding them with updated configuration for
//    this protocol version, along with their server ID. The remove/add cycle
//    is required to populate their server ID. Note that removing must be done
//    by ID, which will be the old server's address.
const (
	ProtocolVersionMin = 0
	ProtocolVersionMax = 3
)

// Config provides any necessary configuration to
// the Raft server
type Config struct {
	// ProtocolVersion allows a Raft server to inter-operate with older
	// Raft servers running an older version of the code. This is used to
	// version the wire protocol as well as Raft-specific log entries that
	// the server uses when _speaking_ to other servers. There is currently
	// no auto-negotiation of versions so all servers must be manually
	// configured with compatible versions. See ProtocolVersionMin and
	// ProtocolVersionMax for the versions of the protocol that this server
	// can _understand_.
	ProtocolVersion int

	// HeartbeatTimeout specifies the time in follower state without
	// a leader before we attempt an election.
	HeartbeatTimeout time.Duration

	// ElectionTimeout specifies the time in candidate state without
	// a leader before we attempt an election.
	ElectionTimeout time.Duration

	// CommitTimeout controls the time without an Apply() operation
	// before we heartbeat to ensure a timely commit. Due to random
	// staggering, may be delayed as much as 2x this value.
	CommitTimeout time.Duration

	// MaxAppendEntries controls the maximum number of append entries
	// to send at once. We want to strike a balance between efficiency
	// and avoiding waste if the follower is going to reject because of
	// an inconsistent log.
	MaxAppendEntries int

	// If we are a member of a cluster, and RemovePeer is invoked for the
	// local node, then we forget all peers and transition into the follower state.
	// If ShutdownOnRemove is is set, we additional shutdown Raft. Otherwise,
	// we can become a leader of a cluster containing only this node.
	ShutdownOnRemove bool

	// TrailingLogs controls how many logs we leave after a snapshot. This is
	// used so that we can quickly replay logs on a follower instead of being
	// forced to send an entire snapshot.
	TrailingLogs uint64

	// SnapshotInterval controls how often we check if we should perform a snapshot.
	// We randomly stagger between this value and 2x this value to avoid the entire
	// cluster from performing a snapshot at once.
	SnapshotInterval time.Duration

	// SnapshotThreshold controls how many outstanding logs there must be before
	// we perform a snapshot. This is to prevent excessive snapshots when we can
	// just replay a small set of logs.
	SnapshotThreshold uint64

	// LeaderLeaseTimeout is used to control how long the "lease" lasts
	// for being the leader without being able to contact a quorum
	// of nodes. If we reach this interval without contact, we will
	// step down as leader.
	LeaderLeaseTimeout time.Duration

	// StartAsLeader forces Raft to start in the leader state. This should
	// never be used except for testing purposes, as it can cause a split-brain.
	StartAsLeader bool

	// The unique ID for this server across all time. When running with
	// ProtocolVersion < 3, you must set this to be the same as the network
	// address of your transport.
	LocalID ServerID

	// NotifyCh is used to provide a channel that will be notified of leadership
	// changes. Raft will block writing to this channel, so it should either be
	// buffered or aggressively consumed.
	NotifyCh chan<- bool

	// LogOutput is used as a sink for logs, unless Logger is specified.
	// Defaults to os.Stderr.
	LogOutput io.Writer

	// Logger is a user-provided logger. If nil, a logger writing to LogOutput
	// is used.
	Logger *log.Logger
}

// DefaultConfig returns a Config with usable defaults.
func DefaultConfig() *Config {
	return &Config{
		ProtocolVersion:    ProtocolVersionMax,
		HeartbeatTimeout:   1000 * time.Millisecond,
		ElectionTimeout:    1000 * time.Millisecond,
		CommitTimeout:      50 * time.Millisecond,
		MaxAppendEntries:   64,
		ShutdownOnRemove:   true,
		TrailingLogs:       10240,
		SnapshotInterval:   120 * time.Second,
		SnapshotThreshold:  8192,
		LeaderLeaseTimeout: 500 * time.Millisecond,
	}
}

// ValidateConfig is used to validate a sane configuration
func ValidateConfig(config *Config) error {
	// We don't actually support running as 0 in the library any more, but
	// we do understand it.
	protocolMin := ProtocolVersionMin
	if protocolMin == 0 {
		protocolMin = 1
	}
	if config.ProtocolVersion < protocolMin ||
		config.ProtocolVersion > ProtocolVersionMax {
		return fmt.Errorf("Protocol version %d must be >= %d and <= %d",
			config.ProtocolVersion, protocolMin, ProtocolVersionMax)
	}
	if len(config.LocalID) == 0 {
		return fmt.Errorf("LocalID cannot be empty")
	}
	if config.HeartbeatTimeout < 5*time.Millisecond {
		return fmt.Errorf("Heartbeat timeout is too low")
	}
	if config.ElectionTimeout < 5*time.Millisecond {
		return fmt.Errorf("Election timeout is too low")
	}
	if config.CommitTimeout < time.Millisecond {
		return fmt.Errorf("Commit timeout is too low")
	}
	if config.MaxAppendEntries <= 0 {
		return fmt.Errorf("MaxAppendEntries must be positive")
	}
	if config.MaxAppendEntries > 1024 {
		return fmt.Errorf("MaxAppendEntries is too large")
	}
	if config.SnapshotInterval < 5*time.Millisecond {
		return fmt.Errorf("Snapshot interval is too low")
	}
	if config.LeaderLeaseTimeout < 5*time.Millisecond {
		return fmt.Errorf("Leader lease timeout is too low")
	}
	if config.LeaderLeaseTimeout > config.HeartbeatTimeout {
		return fmt.Errorf("Leader lease timeout cannot be larger than heartbeat timeout")
	}
	if config.ElectionTimeout < config.HeartbeatTimeout {
		return fmt.Errorf("Election timeout must be equal or greater than Heartbeat Timeout")
	}
	return nil
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 Couchbase, Inc.
//  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 bleve

import (
	"expvar"
	"io/ioutil"
	"log"
	"time"

	"github.com/blevesearch/bleve/index/upside_down"
	"github.com/blevesearch/bleve/registry"

	// token maps
	_ "github.com/blevesearch/bleve/analysis/token_map"

	// fragment formatters
	_ "github.com/blevesearch/bleve/search/highlight/fragment_formatters/ansi"
	_ "github.com/blevesearch/bleve/search/highlight/fragment_formatters/html"

	// fragmenters
	_ "github.com/blevesearch/bleve/search/highlight/fragmenters/simple"

	// highlighters
	_ "github.com/blevesearch/bleve/search/highlight/highlighters/simple"

	// char filters
	_ "github.com/blevesearch/bleve/analysis/char_filters/html_char_filter"
	_ "github.com/blevesearch/bleve/analysis/char_filters/regexp_char_filter"
	_ "github.com/blevesearch/bleve/analysis/char_filters/zero_width_non_joiner"

	// analyzers
	_ "github.com/blevesearch/bleve/analysis/analyzers/custom_analyzer"
	_ "github.com/blevesearch/bleve/analysis/analyzers/keyword_analyzer"
	_ "github.com/blevesearch/bleve/analysis/analyzers/simple_analyzer"
	_ "github.com/blevesearch/bleve/analysis/analyzers/standard_analyzer"

	// token filters
	_ "github.com/blevesearch/bleve/analysis/token_filters/apostrophe_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/compound"
	_ "github.com/blevesearch/bleve/analysis/token_filters/edge_ngram_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/elision_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/keyword_marker_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/length_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/lower_case_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/ngram_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/shingle"
	_ "github.com/blevesearch/bleve/analysis/token_filters/stop_tokens_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/truncate_token_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/unicode_normalize"

	// tokenizers
	_ "github.com/blevesearch/bleve/analysis/tokenizers/exception"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/regexp_tokenizer"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/single_token"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/unicode"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/whitespace_tokenizer"

	// date time parsers
	_ "github.com/blevesearch/bleve/analysis/datetime_parsers/datetime_optional"
	_ "github.com/blevesearch/bleve/analysis/datetime_parsers/flexible_go"

	// languages
	_ "github.com/blevesearch/bleve/analysis/language/ar"
	_ "github.com/blevesearch/bleve/analysis/language/bg"
	_ "github.com/blevesearch/bleve/analysis/language/ca"
	_ "github.com/blevesearch/bleve/analysis/language/cjk"
	_ "github.com/blevesearch/bleve/analysis/language/ckb"
	_ "github.com/blevesearch/bleve/analysis/language/cs"
	_ "github.com/blevesearch/bleve/analysis/language/da"
	_ "github.com/blevesearch/bleve/analysis/language/de"
	_ "github.com/blevesearch/bleve/analysis/language/el"
	_ "github.com/blevesearch/bleve/analysis/language/en"
	_ "github.com/blevesearch/bleve/analysis/language/es"
	_ "github.com/blevesearch/bleve/analysis/language/eu"
	_ "github.com/blevesearch/bleve/analysis/language/fa"
	_ "github.com/blevesearch/bleve/analysis/language/fi"
	_ "github.com/blevesearch/bleve/analysis/language/fr"
	_ "github.com/blevesearch/bleve/analysis/language/ga"
	_ "github.com/blevesearch/bleve/analysis/language/gl"
	_ "github.com/blevesearch/bleve/analysis/language/hi"
	_ "github.com/blevesearch/bleve/analysis/language/hu"
	_ "github.com/blevesearch/bleve/analysis/language/hy"
	_ "github.com/blevesearch/bleve/analysis/language/id"
	_ "github.com/blevesearch/bleve/analysis/language/in"
	_ "github.com/blevesearch/bleve/analysis/language/it"
	_ "github.com/blevesearch/bleve/analysis/language/nl"
	_ "github.com/blevesearch/bleve/analysis/language/no"
	_ "github.com/blevesearch/bleve/analysis/language/pt"
	_ "github.com/blevesearch/bleve/analysis/language/ro"
	_ "github.com/blevesearch/bleve/analysis/language/ru"
	_ "github.com/blevesearch/bleve/analysis/language/sv"
	_ "github.com/blevesearch/bleve/analysis/language/th"
	_ "github.com/blevesearch/bleve/analysis/language/tr"

	// kv stores
	_ "github.com/blevesearch/bleve/index/store/boltdb"
	_ "github.com/blevesearch/bleve/index/store/goleveldb"
	_ "github.com/blevesearch/bleve/index/store/gtreap"
	_ "github.com/blevesearch/bleve/index/store/inmem"

	// byte array converters
	_ "github.com/blevesearch/bleve/analysis/byte_array_converters/ignore"
	_ "github.com/blevesearch/bleve/analysis/byte_array_converters/json"
	_ "github.com/blevesearch/bleve/analysis/byte_array_converters/string"
)

var bleveExpVar = expvar.NewMap("bleve")

type configuration struct {
	Cache                  *registry.Cache
	DefaultHighlighter     string
	DefaultKVStore         string
	SlowSearchLogThreshold time.Duration
	analysisQueue          *upside_down.AnalysisQueue
}

func newConfiguration() *configuration {
	return &configuration{
		Cache:         registry.NewCache(),
		analysisQueue: upside_down.NewAnalysisQueue(4),
	}
}

// Config contains library level configuration
var Config *configuration

func init() {
	bootStart := time.Now()

	// build the default configuration
	Config = newConfiguration()

	_, err := Config.Cache.DefineFragmentFormatter("highlightSpanHTML",
		map[string]interface{}{
			"type":   "html",
			"before": `<span class="highlight">`,
			"after":  `</span>`,
		})
	if err != nil {
		panic(err)
	}

	_, err = Config.Cache.DefineHighlighter("html",
		map[string]interface{}{
			"type":       "simple",
			"fragmenter": "simple",
			"formatter":  "highlightSpanHTML",
		})
	if err != nil {
		panic(err)
	}

	_, err = Config.Cache.DefineHighlighter("ansi",
		map[string]interface{}{
			"type":       "simple",
			"fragmenter": "simple",
			"formatter":  "ansi",
		})
	if err != nil {
		panic(err)
	}

	// set the default highlighter
	Config.DefaultHighlighter = "html"

	// default kv store
	Config.DefaultKVStore = "boltdb"

	bootDuration := time.Since(bootStart)
	bleveExpVar.Add("bootDuration", int64(bootDuration))
}

var logger = log.New(ioutil.Discard, "bleve", log.LstdFlags)

// SetLog sets the logger used for logging
// by default log messages are sent to ioutil.Discard
func SetLog(l *log.Logger) {
	logger = l
}
<commit_msg>changed HTML highlighter to use html mark tag<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  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 bleve

import (
	"expvar"
	"io/ioutil"
	"log"
	"time"

	"github.com/blevesearch/bleve/index/upside_down"
	"github.com/blevesearch/bleve/registry"

	// token maps
	_ "github.com/blevesearch/bleve/analysis/token_map"

	// fragment formatters
	_ "github.com/blevesearch/bleve/search/highlight/fragment_formatters/ansi"
	_ "github.com/blevesearch/bleve/search/highlight/fragment_formatters/html"

	// fragmenters
	_ "github.com/blevesearch/bleve/search/highlight/fragmenters/simple"

	// highlighters
	_ "github.com/blevesearch/bleve/search/highlight/highlighters/simple"

	// char filters
	_ "github.com/blevesearch/bleve/analysis/char_filters/html_char_filter"
	_ "github.com/blevesearch/bleve/analysis/char_filters/regexp_char_filter"
	_ "github.com/blevesearch/bleve/analysis/char_filters/zero_width_non_joiner"

	// analyzers
	_ "github.com/blevesearch/bleve/analysis/analyzers/custom_analyzer"
	_ "github.com/blevesearch/bleve/analysis/analyzers/keyword_analyzer"
	_ "github.com/blevesearch/bleve/analysis/analyzers/simple_analyzer"
	_ "github.com/blevesearch/bleve/analysis/analyzers/standard_analyzer"

	// token filters
	_ "github.com/blevesearch/bleve/analysis/token_filters/apostrophe_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/compound"
	_ "github.com/blevesearch/bleve/analysis/token_filters/edge_ngram_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/elision_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/keyword_marker_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/length_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/lower_case_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/ngram_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/shingle"
	_ "github.com/blevesearch/bleve/analysis/token_filters/stop_tokens_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/truncate_token_filter"
	_ "github.com/blevesearch/bleve/analysis/token_filters/unicode_normalize"

	// tokenizers
	_ "github.com/blevesearch/bleve/analysis/tokenizers/exception"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/regexp_tokenizer"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/single_token"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/unicode"
	_ "github.com/blevesearch/bleve/analysis/tokenizers/whitespace_tokenizer"

	// date time parsers
	_ "github.com/blevesearch/bleve/analysis/datetime_parsers/datetime_optional"
	_ "github.com/blevesearch/bleve/analysis/datetime_parsers/flexible_go"

	// languages
	_ "github.com/blevesearch/bleve/analysis/language/ar"
	_ "github.com/blevesearch/bleve/analysis/language/bg"
	_ "github.com/blevesearch/bleve/analysis/language/ca"
	_ "github.com/blevesearch/bleve/analysis/language/cjk"
	_ "github.com/blevesearch/bleve/analysis/language/ckb"
	_ "github.com/blevesearch/bleve/analysis/language/cs"
	_ "github.com/blevesearch/bleve/analysis/language/da"
	_ "github.com/blevesearch/bleve/analysis/language/de"
	_ "github.com/blevesearch/bleve/analysis/language/el"
	_ "github.com/blevesearch/bleve/analysis/language/en"
	_ "github.com/blevesearch/bleve/analysis/language/es"
	_ "github.com/blevesearch/bleve/analysis/language/eu"
	_ "github.com/blevesearch/bleve/analysis/language/fa"
	_ "github.com/blevesearch/bleve/analysis/language/fi"
	_ "github.com/blevesearch/bleve/analysis/language/fr"
	_ "github.com/blevesearch/bleve/analysis/language/ga"
	_ "github.com/blevesearch/bleve/analysis/language/gl"
	_ "github.com/blevesearch/bleve/analysis/language/hi"
	_ "github.com/blevesearch/bleve/analysis/language/hu"
	_ "github.com/blevesearch/bleve/analysis/language/hy"
	_ "github.com/blevesearch/bleve/analysis/language/id"
	_ "github.com/blevesearch/bleve/analysis/language/in"
	_ "github.com/blevesearch/bleve/analysis/language/it"
	_ "github.com/blevesearch/bleve/analysis/language/nl"
	_ "github.com/blevesearch/bleve/analysis/language/no"
	_ "github.com/blevesearch/bleve/analysis/language/pt"
	_ "github.com/blevesearch/bleve/analysis/language/ro"
	_ "github.com/blevesearch/bleve/analysis/language/ru"
	_ "github.com/blevesearch/bleve/analysis/language/sv"
	_ "github.com/blevesearch/bleve/analysis/language/th"
	_ "github.com/blevesearch/bleve/analysis/language/tr"

	// kv stores
	_ "github.com/blevesearch/bleve/index/store/boltdb"
	_ "github.com/blevesearch/bleve/index/store/goleveldb"
	_ "github.com/blevesearch/bleve/index/store/gtreap"
	_ "github.com/blevesearch/bleve/index/store/inmem"

	// byte array converters
	_ "github.com/blevesearch/bleve/analysis/byte_array_converters/ignore"
	_ "github.com/blevesearch/bleve/analysis/byte_array_converters/json"
	_ "github.com/blevesearch/bleve/analysis/byte_array_converters/string"
)

var bleveExpVar = expvar.NewMap("bleve")

type configuration struct {
	Cache                  *registry.Cache
	DefaultHighlighter     string
	DefaultKVStore         string
	SlowSearchLogThreshold time.Duration
	analysisQueue          *upside_down.AnalysisQueue
}

func newConfiguration() *configuration {
	return &configuration{
		Cache:         registry.NewCache(),
		analysisQueue: upside_down.NewAnalysisQueue(4),
	}
}

// Config contains library level configuration
var Config *configuration

func init() {
	bootStart := time.Now()

	// build the default configuration
	Config = newConfiguration()

	_, err := Config.Cache.DefineFragmentFormatter("highlightSpanHTML",
		map[string]interface{}{
			"type":   "html",
			"before": `<mark>`,
			"after":  `</mark>`,
		})
	if err != nil {
		panic(err)
	}

	_, err = Config.Cache.DefineHighlighter("html",
		map[string]interface{}{
			"type":       "simple",
			"fragmenter": "simple",
			"formatter":  "highlightSpanHTML",
		})
	if err != nil {
		panic(err)
	}

	_, err = Config.Cache.DefineHighlighter("ansi",
		map[string]interface{}{
			"type":       "simple",
			"fragmenter": "simple",
			"formatter":  "ansi",
		})
	if err != nil {
		panic(err)
	}

	// set the default highlighter
	Config.DefaultHighlighter = "html"

	// default kv store
	Config.DefaultKVStore = "boltdb"

	bootDuration := time.Since(bootStart)
	bleveExpVar.Add("bootDuration", int64(bootDuration))
}

var logger = log.New(ioutil.Discard, "bleve", log.LstdFlags)

// SetLog sets the logger used for logging
// by default log messages are sent to ioutil.Discard
func SetLog(l *log.Logger) {
	logger = l
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
)

type configFile struct {
	Listen string

	Threads int
	Workers int

	Retries    int
	APITimeout int

	RequestsPerSecond int
	ErrorPeriod       int
	MaxErrors         int

	CacheDir  string
	FastStart bool

	Secret               string `xml:",omitempty"`
	ProxyAddr            string `xml:",omitempty"`
	RealRemoteAddrHeader string `xml:",omitempty"`
	UserAgent            string `xml:",omitempty"`

	Logging logConfig
}

type logConfig struct {
	LogFile string

	LogRequests bool
	CensorLog   bool

	Debug        bool
	DebugLogFile string
}

var conf configFile

func genSecret() string {
	buf := make([]byte, 32)
	io.ReadFull(rand.Reader, buf)
	return fmt.Sprintf("%x", buf)
}

var defaultConfig = configFile{
	Listen:  "127.0.0.1:3748",
	Threads: 0,
	Workers: 10,

	RequestsPerSecond: 30,

	ErrorPeriod: 60,
	MaxErrors:   75,

	Retries:    3,
	APITimeout: 60,

	CacheDir: "cache/",
	Logging: logConfig{
		CensorLog: true,
	},
}

func createConfig() {
	//  Secret for eventual control code
	//	defaultConfig.Secret = genSecret()
	confXML, _ := xml.MarshalIndent(defaultConfig, "", "  ")

	err := ioutil.WriteFile("apiproxy.xml.default", confXML, 0600)
	if err != nil {
		log.Fatalf("Error creating config file apiproxy.xml.default: %s", err)
	} else {
		log.Fatalf("Created new config file apiproxy.xml.default")
	}
}

func loadConfig(filename string) (configFile, error) {
	conf, err := ioutil.ReadFile(filename)
	if err != nil {
		return defaultConfig, err
	}

	newConfig := defaultConfig
	err = xml.Unmarshal(conf, &newConfig)
	if err != nil {
		return defaultConfig, err
	}

	if newConfig.CacheDir == "" {
		return defaultConfig, fmt.Errorf("Need cache directory")
	}

	if newConfig.Logging.Debug {
		debug = true
	}

	return newConfig, nil
}
<commit_msg>return to sane error limit<commit_after>package main

import (
	"crypto/rand"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
)

type configFile struct {
	Listen string

	Threads int
	Workers int

	Retries    int
	APITimeout int

	RequestsPerSecond int
	ErrorPeriod       int
	MaxErrors         int

	CacheDir  string
	FastStart bool

	Secret               string `xml:",omitempty"`
	ProxyAddr            string `xml:",omitempty"`
	RealRemoteAddrHeader string `xml:",omitempty"`
	UserAgent            string `xml:",omitempty"`

	Logging logConfig
}

type logConfig struct {
	LogFile string

	LogRequests bool
	CensorLog   bool

	Debug        bool
	DebugLogFile string
}

var conf configFile

func genSecret() string {
	buf := make([]byte, 32)
	io.ReadFull(rand.Reader, buf)
	return fmt.Sprintf("%x", buf)
}

var defaultConfig = configFile{
	Listen:  "127.0.0.1:3748",
	Threads: 0,
	Workers: 10,

	// As per CCP FoxFour.
	RequestsPerSecond: 30,

	// According to CCP FocFour error limit seems to be
	// 300 errors over 3 minutes.
	ErrorPeriod: 180,
	MaxErrors:   250,

	Retries:    3,
	APITimeout: 60,

	CacheDir: "cache/",
	Logging: logConfig{
		CensorLog: true,
	},
}

func createConfig() {
	//  Secret for eventual control code
	//	defaultConfig.Secret = genSecret()
	confXML, _ := xml.MarshalIndent(defaultConfig, "", "  ")

	err := ioutil.WriteFile("apiproxy.xml.default", confXML, 0600)
	if err != nil {
		log.Fatalf("Error creating config file apiproxy.xml.default: %s", err)
	} else {
		log.Fatalf("Created new config file apiproxy.xml.default")
	}
}

func loadConfig(filename string) (configFile, error) {
	conf, err := ioutil.ReadFile(filename)
	if err != nil {
		return defaultConfig, err
	}

	newConfig := defaultConfig
	err = xml.Unmarshal(conf, &newConfig)
	if err != nil {
		return defaultConfig, err
	}

	if newConfig.CacheDir == "" {
		return defaultConfig, fmt.Errorf("Need cache directory")
	}

	if newConfig.Logging.Debug {
		debug = true
	}

	return newConfig, nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/keybase/go-libkb"
	"github.com/keybase/protocol/go"
	"github.com/maxtaco/go-framed-msgpack-rpc/rpc2"
)

type ConfigHandler struct {
	xp *rpc2.Transport
}

func (h ConfigHandler) GetCurrentStatus() (res keybase_1.GetCurrentStatusRes, err error) {
	var cs libkb.CurrentStatus
	cs, err = libkb.GetCurrentStatus()
	if err == nil {
		res.Configured = cs.Configured
		res.Registered = cs.Registered
		res.LoggedIn = cs.LoggedIn
		res.PublicKeySelected = cs.PublicKeySelected
	}
	return
}
<commit_msg>Address keybase/go-libkb#69<commit_after>package main

import (
	"github.com/keybase/go-libkb"
	"github.com/keybase/protocol/go"
	"github.com/maxtaco/go-framed-msgpack-rpc/rpc2"
)

type ConfigHandler struct {
	xp *rpc2.Transport
}

func (h ConfigHandler) GetCurrentStatus() (res keybase_1.GetCurrentStatusRes, err error) {
	var cs libkb.CurrentStatus
	if cs, err = libkb.GetCurrentStatus(); err == nil {
		res = cs.Export()
	}
	return
}
<|endoftext|>