<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>Removed cache for now, the cache headers already reduce the load and if we cache we need to do it better anyway.<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
}

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
}

func loadImage(request Request, w http.ResponseWriter, r *http.Request) {
	log.Printf("Loading image: %v", request)
	avatar := retrieveImage(request, w, r)
	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)
}
<|endoftext|>


<commit_before>package v7action_test

import (
	"code.cloudfoundry.org/cli/actor/actionerror"
	. "code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
	"errors"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Organization Quota Actions", func() {
	var (
		actor                     *Actor
		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
	)

	BeforeEach(func() {
		actor, fakeCloudControllerClient, _, _, _, _ = NewTestActor()
	})

	Describe("GetOrganizationQuotas", func() {
		var (
			quotas     []OrganizationQuota
			warnings   Warnings
			executeErr error
		)

		JustBeforeEach(func() {
			quotas, warnings, executeErr = actor.GetOrganizationQuotas()
		})

		When("getting organization quotas", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{
						ccv3.OrgQuota{
							GUID: "quota-guid",
							Name: "kiwi",
						},
						ccv3.OrgQuota{
							GUID: "quota-2-guid",
							Name: "strawberry",
						},
					},
					ccv3.Warnings{"some-quota-warning"},
					nil,
				)
			})

			It("queries the API and returns organization quotas", func() {
				Expect(executeErr).ToNot(HaveOccurred())

				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))

				Expect(quotas).To(ConsistOf(
					OrganizationQuota{
						GUID: "quota-guid",
						Name: "kiwi",
					},
					OrganizationQuota{
						GUID: "quota-2-guid",
						Name: "strawberry",
					},
				))
				Expect(warnings).To(ConsistOf("some-quota-warning"))
			})
		})
	})

	Describe("GetOrganizationQuotaByName", func() {
		var (
			quotaName  string
			quota      OrganizationQuota
			warnings   Warnings
			executeErr error
		)

		BeforeEach(func() {
			quotaName = "quota-name"
		})

		JustBeforeEach(func() {
			quota, warnings, executeErr = actor.GetOrganizationQuotaByName(quotaName)
		})

		When("when the API layer call returns an error", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{},
					ccv3.Warnings{"some-quota-warning"},
					errors.New("list-error"),
				)
			})

			It("returns the error and prints warnings", func() {
				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))

				Expect(warnings).To(ConsistOf("some-quota-warning"))
				Expect(executeErr).To(MatchError("list-error"))
				Expect(quota).To(Equal(OrganizationQuota{}))
			})
		})

		When("when the org quota could not be found", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{},
					ccv3.Warnings{"some-quota-warning"},
					nil,
				)
			})

			It("returns the error and prints warnings", func() {
				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))

				Expect(warnings).To(ConsistOf("some-quota-warning"))
				Expect(executeErr).To(MatchError(actionerror.OrganizationQuotaNotFoundForNameError{Name: quotaName}))
				Expect(quota).To(Equal(OrganizationQuota{}))
			})
		})

		When("getting a single quota by name", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{
						ccv3.OrgQuota{
							GUID: "quota-guid",
							Name: quotaName,
						},
					},
					ccv3.Warnings{"some-quota-warning"},
					nil,
				)
			})

			It("queries the API and returns the matching organization quota", func() {
				Expect(executeErr).ToNot(HaveOccurred())

				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))
				query := fakeCloudControllerClient.GetOrganizationQuotasArgsForCall(0)
				Expect(query).To(ConsistOf(
					ccv3.Query{Key: ccv3.NameFilter, Values: []string{quotaName}},
				))

				Expect(warnings).To(ConsistOf("some-quota-warning"))
				Expect(quota).To(Equal(OrganizationQuota{GUID: "quota-guid", Name: quotaName}))
			})
		})
	})
})
<commit_msg>Run goimports on v7action/organization_quota_test<commit_after>package v7action_test

import (
	"errors"

	"code.cloudfoundry.org/cli/actor/actionerror"
	. "code.cloudfoundry.org/cli/actor/v7action"
	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Organization Quota Actions", func() {
	var (
		actor                     *Actor
		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
	)

	BeforeEach(func() {
		actor, fakeCloudControllerClient, _, _, _, _ = NewTestActor()
	})

	Describe("GetOrganizationQuotas", func() {
		var (
			quotas     []OrganizationQuota
			warnings   Warnings
			executeErr error
		)

		JustBeforeEach(func() {
			quotas, warnings, executeErr = actor.GetOrganizationQuotas()
		})

		When("getting organization quotas", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{
						ccv3.OrgQuota{
							GUID: "quota-guid",
							Name: "kiwi",
						},
						ccv3.OrgQuota{
							GUID: "quota-2-guid",
							Name: "strawberry",
						},
					},
					ccv3.Warnings{"some-quota-warning"},
					nil,
				)
			})

			It("queries the API and returns organization quotas", func() {
				Expect(executeErr).ToNot(HaveOccurred())

				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))

				Expect(quotas).To(ConsistOf(
					OrganizationQuota{
						GUID: "quota-guid",
						Name: "kiwi",
					},
					OrganizationQuota{
						GUID: "quota-2-guid",
						Name: "strawberry",
					},
				))
				Expect(warnings).To(ConsistOf("some-quota-warning"))
			})
		})
	})

	Describe("GetOrganizationQuotaByName", func() {
		var (
			quotaName  string
			quota      OrganizationQuota
			warnings   Warnings
			executeErr error
		)

		BeforeEach(func() {
			quotaName = "quota-name"
		})

		JustBeforeEach(func() {
			quota, warnings, executeErr = actor.GetOrganizationQuotaByName(quotaName)
		})

		When("when the API layer call returns an error", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{},
					ccv3.Warnings{"some-quota-warning"},
					errors.New("list-error"),
				)
			})

			It("returns the error and prints warnings", func() {
				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))

				Expect(warnings).To(ConsistOf("some-quota-warning"))
				Expect(executeErr).To(MatchError("list-error"))
				Expect(quota).To(Equal(OrganizationQuota{}))
			})
		})

		When("when the org quota could not be found", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{},
					ccv3.Warnings{"some-quota-warning"},
					nil,
				)
			})

			It("returns the error and prints warnings", func() {
				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))

				Expect(warnings).To(ConsistOf("some-quota-warning"))
				Expect(executeErr).To(MatchError(actionerror.OrganizationQuotaNotFoundForNameError{Name: quotaName}))
				Expect(quota).To(Equal(OrganizationQuota{}))
			})
		})

		When("getting a single quota by name", func() {
			BeforeEach(func() {
				fakeCloudControllerClient.GetOrganizationQuotasReturns(
					[]ccv3.OrgQuota{
						ccv3.OrgQuota{
							GUID: "quota-guid",
							Name: quotaName,
						},
					},
					ccv3.Warnings{"some-quota-warning"},
					nil,
				)
			})

			It("queries the API and returns the matching organization quota", func() {
				Expect(executeErr).ToNot(HaveOccurred())

				Expect(fakeCloudControllerClient.GetOrganizationQuotasCallCount()).To(Equal(1))
				query := fakeCloudControllerClient.GetOrganizationQuotasArgsForCall(0)
				Expect(query).To(ConsistOf(
					ccv3.Query{Key: ccv3.NameFilter, Values: []string{quotaName}},
				))

				Expect(warnings).To(ConsistOf("some-quota-warning"))
				Expect(quota).To(Equal(OrganizationQuota{GUID: "quota-guid", Name: quotaName}))
			})
		})
	})
})
<|endoftext|>


<commit_before>// Version 1.82
// Supports Windows, Linux, Mac, and Raspberry Pi, Beagle Bone Black

package main

import (
	"errors"
	"flag"
	"fmt"
	"go/build"
	"log"
	"net"
	"net/http"
	"os"
	//"net/http/pprof"
	"runtime/debug"
	"text/template"
	"time"
)

var (
	version      = "1.82"
	versionFloat = float32(1.82)
	addr         = flag.String("addr", ":8989", "http service address")
	//assets       = flag.String("assets", defaultAssetPath(), "path to assets")
	verbose = flag.Bool("v", true, "show debug logging")
	//verbose = flag.Bool("v", false, "show debug logging")
	//homeTempl *template.Template
	isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later")

	// regular expression to sort the serial port list
	// typically this wouldn't be provided, but if the user wants to clean
	// up their list with a regexp so it's cleaner inside their end-user interface
	// such as ChiliPeppr, this can make the massive list that Linux gives back
	// to you be a bit more manageable
	regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list")

	// allow garbageCollection()
	//isGC = flag.Bool("gc", false, "Is garbage collection on? Off by default.")
	//isGC = flag.Bool("gc", true, "Is garbage collection on? Off by default.")
	gcType = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)")

	// whether to do buffer flow debugging
	bufFlowDebugType = flag.String("bufflowdebug", "off", "off = (default) We do not send back any debug JSON, on = We will send back a JSON response with debug info based on the configuration of the buffer flow that the user picked")

	// hostname. allow user to override, otherwise we look it up
	hostname = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")
)

type NullWriter int

func (NullWriter) Write([]byte) (int, error) { return 0, nil }

func defaultAssetPath() string {
	//p, err := build.Default.Import("gary.burd.info/go-websocket-chat", "", build.FindOnly)
	p, err := build.Default.Import("github.com/johnlauer/serial-port-json-server", "", build.FindOnly)
	if err != nil {
		return "."
	}
	return p.Dir
}

func homeHandler(c http.ResponseWriter, req *http.Request) {
	homeTemplate.Execute(c, req.Host)
}

func launchSelfLater() {
	log.Println("Going to launch myself 5 seconds later.")
	time.Sleep(2 * 1000 * time.Millisecond)
	log.Println("Done waiting 5 secs. Now launching...")
}

func main() {

	flag.Parse()
	// setup logging
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	// see if we are supposed to wait 5 seconds
	if *isLaunchSelf {
		launchSelfLater()
	}

	//getList()
	f := flag.Lookup("addr")
	log.Println("Version:" + version)

	// hostname
	hn, _ := os.Hostname()
	if *hostname == "unknown-hostname" {
		*hostname = hn
	}
	log.Println("Hostname:", *hostname)

	// turn off garbage collection
	// this is dangerous, as u could overflow memory
	//if *isGC {
	if *gcType == "std" {
		log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.")
	} else if *gcType == "max" {
		log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.")
	} else {
		log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.")
		debug.SetGCPercent(-1)
	}

	ip, err := externalIP()
	if err != nil {
		log.Println(err)
	}

	log.Print("Starting server and websocket on " + ip + "" + f.Value.String())
	//homeTempl = template.Must(template.ParseFiles(filepath.Join(*assets, "home.html")))

	log.Println("The Serial Port JSON Server is now running.")
	log.Println("If you are using ChiliPeppr, you may go back to it and connect to this server.")

	// see if they provided a regex filter
	if len(*regExpFilter) > 0 {
		log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter)
	}

	// list serial ports
	portList, _ := GetList()
	/*if errSys != nil {
		log.Printf("Got system error trying to retrieve serial port list. Err:%v\n", errSys)
		log.Fatal("Exiting")
	}*/
	log.Println("Your serial ports:")
	if len(portList) == 0 {
		log.Println("\tThere are no serial ports to list.")
	}
	for _, element := range portList {
		log.Printf("\t%v\n", element)

	}

	if !*verbose {
		log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
		log.SetOutput(new(NullWriter)) //route all logging to nullwriter
	}

	// launch the hub routine which is the singleton for the websocket server
	go h.run()
	// launch our serial port routine
	go sh.run()
	// launch our dummy data routine
	//go d.run()

	go func() {
		http.HandleFunc("/", homeHandler)
		http.HandleFunc("/ws", wsHandler)
		if err := http.ListenAndServe(*addr, nil); err != nil {
			fmt.Printf("Error trying to bind to port: %v, so exiting...", err)
			log.Fatal("Error ListenAndServe:", err)
		}
	}()

	setupSysTray()
}

func externalIP() (string, error) {
	//log.Println("Getting external IP")
	ifaces, err := net.Interfaces()
	if err != nil {
		log.Println("Got err getting external IP addr")
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			//log.Println("Iface down")
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			//log.Println("Loopback")
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			log.Println("Got err on iface.Addrs()")
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				//log.Println("Ip was nil or loopback")
				continue
			}
			ip = ip.To4()
			if ip == nil {
				//log.Println("Was not ipv4 addr")
				continue // not an ipv4 address
			}
			//log.Println("IP is ", ip.String())
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml))

// If you navigate to this server's homepage, you'll get this HTML
// so you can directly interact with the serial port server
const homeTemplateHtml = `<!DOCTYPE html>

<title>Serial Port Example</title>

<form id="form">
    <input type="submit" value="Send" />
    <input type="text" id="msg" size="64"/>
</form>

`
<commit_msg>add uploadHandler hook<commit_after>// Version 1.82
// Supports Windows, Linux, Mac, and Raspberry Pi, Beagle Bone Black

package main

import (
	"errors"
	"flag"
	"fmt"
	"go/build"
	"log"
	"net"
	"net/http"
	"os"
	//"net/http/pprof"
	"runtime/debug"
	"text/template"
	"time"
)

var (
	version      = "1.82"
	versionFloat = float32(1.82)
	addr         = flag.String("addr", ":8989", "http service address")
	//assets       = flag.String("assets", defaultAssetPath(), "path to assets")
	verbose = flag.Bool("v", true, "show debug logging")
	//verbose = flag.Bool("v", false, "show debug logging")
	//homeTempl *template.Template
	isLaunchSelf = flag.Bool("ls", false, "launch self 5 seconds later")

	// regular expression to sort the serial port list
	// typically this wouldn't be provided, but if the user wants to clean
	// up their list with a regexp so it's cleaner inside their end-user interface
	// such as ChiliPeppr, this can make the massive list that Linux gives back
	// to you be a bit more manageable
	regExpFilter = flag.String("regex", "usb|acm|com", "Regular expression to filter serial port list")

	// allow garbageCollection()
	//isGC = flag.Bool("gc", false, "Is garbage collection on? Off by default.")
	//isGC = flag.Bool("gc", true, "Is garbage collection on? Off by default.")
	gcType = flag.String("gc", "std", "Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)")

	// whether to do buffer flow debugging
	bufFlowDebugType = flag.String("bufflowdebug", "off", "off = (default) We do not send back any debug JSON, on = We will send back a JSON response with debug info based on the configuration of the buffer flow that the user picked")

	// hostname. allow user to override, otherwise we look it up
	hostname = flag.String("hostname", "unknown-hostname", "Override the hostname we get from the OS")
)

type NullWriter int

func (NullWriter) Write([]byte) (int, error) { return 0, nil }

func defaultAssetPath() string {
	//p, err := build.Default.Import("gary.burd.info/go-websocket-chat", "", build.FindOnly)
	p, err := build.Default.Import("github.com/johnlauer/serial-port-json-server", "", build.FindOnly)
	if err != nil {
		return "."
	}
	return p.Dir
}

func homeHandler(c http.ResponseWriter, req *http.Request) {
	homeTemplate.Execute(c, req.Host)
}

func launchSelfLater() {
	log.Println("Going to launch myself 5 seconds later.")
	time.Sleep(2 * 1000 * time.Millisecond)
	log.Println("Done waiting 5 secs. Now launching...")
}

func main() {

	flag.Parse()
	// setup logging
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	// see if we are supposed to wait 5 seconds
	if *isLaunchSelf {
		launchSelfLater()
	}

	//getList()
	f := flag.Lookup("addr")
	log.Println("Version:" + version)

	// hostname
	hn, _ := os.Hostname()
	if *hostname == "unknown-hostname" {
		*hostname = hn
	}
	log.Println("Hostname:", *hostname)

	// turn off garbage collection
	// this is dangerous, as u could overflow memory
	//if *isGC {
	if *gcType == "std" {
		log.Println("Garbage collection is on using Standard mode, meaning we just let Golang determine when to garbage collect.")
	} else if *gcType == "max" {
		log.Println("Garbage collection is on for MAXIMUM real-time collecting on each send/recv from serial port. Higher CPU, but less stopping of the world to garbage collect since it is being done on a constant basis.")
	} else {
		log.Println("Garbage collection is off. Memory use will grow unbounded. You WILL RUN OUT OF RAM unless you send in the gc command to manually force garbage collection. Lower CPU, but progressive memory footprint.")
		debug.SetGCPercent(-1)
	}

	ip, err := externalIP()
	if err != nil {
		log.Println(err)
	}

	log.Print("Starting server and websocket on " + ip + "" + f.Value.String())
	//homeTempl = template.Must(template.ParseFiles(filepath.Join(*assets, "home.html")))

	log.Println("The Serial Port JSON Server is now running.")
	log.Println("If you are using ChiliPeppr, you may go back to it and connect to this server.")

	// see if they provided a regex filter
	if len(*regExpFilter) > 0 {
		log.Printf("You specified a serial port regular expression filter: %v\n", *regExpFilter)
	}

	// list serial ports
	portList, _ := GetList()
	/*if errSys != nil {
		log.Printf("Got system error trying to retrieve serial port list. Err:%v\n", errSys)
		log.Fatal("Exiting")
	}*/
	log.Println("Your serial ports:")
	if len(portList) == 0 {
		log.Println("\tThere are no serial ports to list.")
	}
	for _, element := range portList {
		log.Printf("\t%v\n", element)

	}

	if !*verbose {
		log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
		log.SetOutput(new(NullWriter)) //route all logging to nullwriter
	}

	// launch the hub routine which is the singleton for the websocket server
	go h.run()
	// launch our serial port routine
	go sh.run()
	// launch our dummy data routine
	//go d.run()

	go func() {
		http.HandleFunc("/", homeHandler)
		http.HandleFunc("/ws", wsHandler)
		http.HandleFunc("/upload", uploadHandler)
		if err := http.ListenAndServe(*addr, nil); err != nil {
			fmt.Printf("Error trying to bind to port: %v, so exiting...", err)
			log.Fatal("Error ListenAndServe:", err)
		}
	}()

	setupSysTray()
}

func externalIP() (string, error) {
	//log.Println("Getting external IP")
	ifaces, err := net.Interfaces()
	if err != nil {
		log.Println("Got err getting external IP addr")
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			//log.Println("Iface down")
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			//log.Println("Loopback")
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			log.Println("Got err on iface.Addrs()")
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				//log.Println("Ip was nil or loopback")
				continue
			}
			ip = ip.To4()
			if ip == nil {
				//log.Println("Was not ipv4 addr")
				continue // not an ipv4 address
			}
			//log.Println("IP is ", ip.String())
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml))

// If you navigate to this server's homepage, you'll get this HTML
// so you can directly interact with the serial port server
const homeTemplateHtml = `<!DOCTYPE html>

<title>Serial Port Example</title>

<form id="form">
    <input type="submit" value="Send" />
    <input type="text" id="msg" size="64"/>
</form>

`
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/artemnikitin/aws-config"
	"github.com/artemnikitin/devicefarm-ci-tool/config"
	"github.com/artemnikitin/devicefarm-ci-tool/errors"
	"github.com/artemnikitin/devicefarm-ci-tool/service"
	"github.com/artemnikitin/devicefarm-ci-tool/tools"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/devicefarm"
)

var (
	project    = flag.String("project", "", "Device Farm project name")
	appPath    = flag.String("app", "", "Path to an app")
	devicePool = flag.String("devices", "Top Devices", "Specify list of devices for tests")
	configJSON = flag.String("config", "", "Path to JSON config")
	wait       = flag.Bool("wait", false, "Wait for run end")
)

func main() {
	flag.Parse()
	if *project == "" || *appPath == "" {
		fmt.Println("Please specify correct parameters!")
		fmt.Println("You should specify:")
		fmt.Println("-project, name of a project in AWS Device Farm")
		fmt.Println("-app, path to an app you want to run")
		os.Exit(1)
	}
	runJob(getAWSClient(), getConfig())
}

func runJob(client *devicefarm.DeviceFarm, config *config.RunConfig) {
	projectArn := service.GetProjectArn(client, *project)
	deviceArn := service.GetDevicePoolArn(client, projectArn, *devicePool)
	appArn, url := service.CreateUpload(client, projectArn, *appPath)
	code := tools.UploadFile(*appPath, url)
	if code != 200 {
		log.Fatal("Can't upload an app to Device Farm")
	}
	service.WaitForAppProcessed(client, appArn)
	runArn, status := service.RunWithConfig(client, deviceArn, projectArn, appArn, config)
	statusCheck(status)
	if *wait {
		service.WaitForRunEnds(client, runArn)
	}
}

func getConfig() *config.RunConfig {
	configFile := &config.RunConfig{}
	if *configJSON != "" {
		bytes, err := ioutil.ReadFile(*configJSON)
		errors.Validate(err, "Can't read config file")
		*configFile = config.Transform(bytes)
	}
	return configFile
}

func getAWSClient() *devicefarm.DeviceFarm {
	config := awsconfig.New()
	if *config.Region != "us-west-2" {
		config.WithRegion("us-west-2")
	}
	session := session.New(config)
	return devicefarm.New(session)
}

func statusCheck(status string) {
	if status == "SCHEDULING" {
		log.Println("Job is started!")
	} else {
		log.Println("Status =", status)
		log.Fatal("Failed to start a job ...")
	}
}
<commit_msg>Fix for issue 1<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/artemnikitin/aws-config"
	"github.com/artemnikitin/devicefarm-ci-tool/config"
	"github.com/artemnikitin/devicefarm-ci-tool/errors"
	"github.com/artemnikitin/devicefarm-ci-tool/service"
	"github.com/artemnikitin/devicefarm-ci-tool/tools"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/devicefarm"
)

var (
	project    = flag.String("project", "", "Device Farm project name")
	appPath    = flag.String("app", "", "Path to an app")
	devicePool = flag.String("devices", "Top Devices", "Specify list of devices for tests")
	configJSON = flag.String("config", "", "Path to JSON config")
	wait       = flag.Bool("wait", false, "Wait for run end")
)

func main() {
	flag.Parse()
	if *project == "" || *appPath == "" {
		fmt.Println("Please specify correct parameters!")
		fmt.Println("You should specify:")
		fmt.Println("-project, name of a project in AWS Device Farm")
		fmt.Println("-app, path to an app you want to run")
		os.Exit(1)
	}
	runJob(getAWSClient(), getConfig())
}

func runJob(client *devicefarm.DeviceFarm, config *config.RunConfig) {
	projectArn := service.GetProjectArn(client, *project)
	if projectArn == "" {
		log.Fatal("Application finished, because it can't retrieve project ARN")
	}
	deviceArn := service.GetDevicePoolArn(client, projectArn, *devicePool)
	appArn, url := service.CreateUpload(client, projectArn, *appPath)
	code := tools.UploadFile(*appPath, url)
	if code != 200 {
		log.Fatal("Can't upload an app to Device Farm")
	}
	service.WaitForAppProcessed(client, appArn)
	runArn, status := service.RunWithConfig(client, deviceArn, projectArn, appArn, config)
	statusCheck(status)
	if *wait {
		service.WaitForRunEnds(client, runArn)
	}
}

func getConfig() *config.RunConfig {
	configFile := &config.RunConfig{}
	if *configJSON != "" {
		bytes, err := ioutil.ReadFile(*configJSON)
		errors.Validate(err, "Can't read config file")
		*configFile = config.Transform(bytes)
	}
	return configFile
}

func getAWSClient() *devicefarm.DeviceFarm {
	config := awsconfig.New()
	if *config.Region != "us-west-2" {
		config.WithRegion("us-west-2")
	}
	session := session.New(config)
	return devicefarm.New(session)
}

func statusCheck(status string) {
	if status == "SCHEDULING" {
		log.Println("Job is started!")
	} else {
		log.Println("Status =", status)
		log.Fatal("Failed to start a job ...")
	}
}
<|endoftext|>


<commit_before>package main

import(
  "os"
  "github.com/codegangsta/cli"
  "github.com/codegangsta/martini"
  "github.com/ricallinson/forgery"
  "github.com/spacedock-io/registry/router"
  "github.com/spacedock-io/registry/auth"
  "github.com/spacedock-io/registry/config"
  "github.com/Southern/logger"
)

const VERSION = "0.0.1"

func Secure(c *mux.Router) (func(http.ResponseWriter, *http.Request)) {
  return func(w http.ResponseWriter, r *http.Request) {

    if auth.Authenticated(w, r) {
      c.ServeHTTP(w, r);
    } else {
      w.WriteHeader(401);
    }
  }
}

func main() {
  server := f.CreateServer()
  server.Use(func (req *f.Request, res *f.Response, next func()) {
    defer next()

    res.Set("X-Docker-Registry-Version", VERSION)
    res.Set("X-Docker-Registry-Config", config.Env)
  })
  server.Use(auth.Middleware)

  app := cli.NewApp()

  app.Name = "Registry"
  app.Usage = "Run a standalone Docker registry"
  app.Version = context.VERSION
  app.Flags = []cli.Flag {
    cli.StringFlag{"port, p", "8080", "Port number", false},
    cli.StringFlag{"index, i", "false", "Index URL", false},
    cli.StringFlag{"env, e", "dev", "Environment", false},
  }

  app.Action = func(c *cli.Context) {
    env := c.String("env")
    if len(env) == 0 {
      env = "dev"
    }
    config.Global = config.Load(env)
    config.Logger = logger.New()

    context.Env = c.String("env")
    context.Port = c.String("port")
    context.Index = c.String("index")

    Routes(server)
    config.Logger.Log("Index listening on port " + fmt.Sprint(c.Int("port")))
    server.Listen(c.Int("port"))
  }

  app.Run(os.Args)
}
<commit_msg>fix: use stackr there<commit_after>package main

import(
  "os"
  "github.com/codegangsta/cli"
  "github.com/codegangsta/martini"
  "github.com/ricallinson/forgery"
  "github.com/ricallinson/stackr"
  "github.com/spacedock-io/registry/router"
  "github.com/spacedock-io/registry/auth"
  "github.com/spacedock-io/registry/config"
  "github.com/Southern/logger"
)

const VERSION = "0.0.1"

func Secure(c *mux.Router) (func(http.ResponseWriter, *http.Request)) {
  return func(w http.ResponseWriter, r *http.Request) {

    if auth.Authenticated(w, r) {
      c.ServeHTTP(w, r);
    } else {
      w.WriteHeader(401);
    }
  }
}

func main() {
  server := f.CreateServer()
  server.Use(func (req *stackr.Request, res *stackr.Response, next func()) {
    defer next()

    res.Set("X-Docker-Registry-Version", VERSION)
    res.Set("X-Docker-Registry-Config", config.Env)
  })
  server.Use(auth.Middleware)

  app := cli.NewApp()

  app.Name = "Registry"
  app.Usage = "Run a standalone Docker registry"
  app.Version = context.VERSION
  app.Flags = []cli.Flag {
    cli.StringFlag{"port, p", "8080", "Port number", false},
    cli.StringFlag{"index, i", "false", "Index URL", false},
    cli.StringFlag{"env, e", "dev", "Environment", false},
  }

  app.Action = func(c *cli.Context) {
    env := c.String("env")
    if len(env) == 0 {
      env = "dev"
    }
    config.Global = config.Load(env)
    config.Logger = logger.New()

    context.Env = c.String("env")
    context.Port = c.String("port")
    context.Index = c.String("index")

    Routes(server)
    config.Logger.Log("Index listening on port " + fmt.Sprint(c.Int("port")))
    server.Listen(c.Int("port"))
  }

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


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
)

type Redirect struct {
	URI          string `json:"uri"`
	Android      string `json:"android"`
	IPhone       string `json:"iphone"`
	IPod         string `json:"ipod"`
	IPad         string `json:"ipad"`
	BlackBerry   string `json:"bb"`
	WindowsPhone string `json:"wp"`
	WinXin       string `json:"wx"`
	Unknown      string `json:"unknown"`
}

type Config struct {
	Address   string      `json:"address"`
	Port      uint16      `json:"port"`
	Redirects []*Redirect `json:"redirect"`
}

var (
	config *Config = new(Config)
)

func handler(w http.ResponseWriter, r *http.Request) {
	var redirect *Redirect = nil
	for _, v := range config.Redirects {
		if v.URI == r.RequestURI {
			redirect = v
			break
		}
	}
	if redirect != nil {
		userAgent := r.UserAgent()
		matched := regexp.MustCompile("Android").MatchString(userAgent)
		if matched {
			log.Println("android", redirect.Android)
			http.Redirect(w, r, redirect.Android, 302)
			return
		}
		matched = regexp.MustCompile("iPod").MatchString(userAgent)
		if matched {
			log.Println("ipod", redirect.IPod)
			http.Redirect(w, r, redirect.IPod, 302)
			return
		}
		matched = regexp.MustCompile("iPhone").MatchString(userAgent)
		if matched {
			log.Println("iphone", redirect.IPhone)
			http.Redirect(w, r, redirect.IPhone, 302)
			return
		}
		matched = regexp.MustCompile("iPad").MatchString(userAgent)
		if matched {
			log.Println("ipad", redirect.IPad)
			http.Redirect(w, r, redirect.IPad, 302)
			return
		}
		matched = regexp.MustCompile("BlackBerry").MatchString(userAgent)
		if matched {
			log.Println("bb", redirect.BlackBerry)
			http.Redirect(w, r, redirect.BlackBerry, 302)
			return
		}
		matched = regexp.MustCompile("IEMobile").MatchString(userAgent)
		if matched {
			log.Println("wp", redirect.WindowsPhone)
			http.Redirect(w, r, redirect.WindowsPhone, 302)
			return
		}
		matched = regexp.MustCompile("MQQBrowser").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched = regexp.MustCompile("TBS").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}

		log.Println("unknown", redirect.Unknown)
		http.Redirect(w, r, redirect.Unknown, 302)
		return
	}
	log.Println("unmatched", config.Redirects[0].Unknown)
	http.Redirect(w, r, config.Redirects[0].Unknown, 302)
}

func main() {
	fh, err := os.Open("config.json")
	if err != nil {
		log.Fatal("opening config.json failed")
		return
	}
	defer fh.Close()
	configcontent, err := ioutil.ReadAll(fh)
	if err != nil {
		log.Fatal("reading config.json failed")
		return
	}

	if err = json.Unmarshal(configcontent, config); err != nil {
		log.Fatal("parsing config.json failed")
		return
	}

	http.HandleFunc("/", handler)
	log.Fatal(
		http.ListenAndServe(
			fmt.Sprintf("%s:%d", config.Address, config.Port),
			nil))
}
<commit_msg>(*)weixin first<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
)

type Redirect struct {
	URI          string `json:"uri"`
	Android      string `json:"android"`
	IPhone       string `json:"iphone"`
	IPod         string `json:"ipod"`
	IPad         string `json:"ipad"`
	BlackBerry   string `json:"bb"`
	WindowsPhone string `json:"wp"`
	WinXin       string `json:"wx"`
	Unknown      string `json:"unknown"`
}

type Config struct {
	Address   string      `json:"address"`
	Port      uint16      `json:"port"`
	Redirects []*Redirect `json:"redirect"`
}

var (
	config *Config = new(Config)
)

func handler(w http.ResponseWriter, r *http.Request) {
	var redirect *Redirect = nil
	for _, v := range config.Redirects {
		if v.URI == r.RequestURI {
			redirect = v
			break
		}
	}
	if redirect != nil {
		userAgent := r.UserAgent()
		matched = regexp.MustCompile("MQQBrowser").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched = regexp.MustCompile("TBS").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched := regexp.MustCompile("Android").MatchString(userAgent)
		if matched {
			log.Println("android", redirect.Android)
			http.Redirect(w, r, redirect.Android, 302)
			return
		}
		matched = regexp.MustCompile("iPod").MatchString(userAgent)
		if matched {
			log.Println("ipod", redirect.IPod)
			http.Redirect(w, r, redirect.IPod, 302)
			return
		}
		matched = regexp.MustCompile("iPhone").MatchString(userAgent)
		if matched {
			log.Println("iphone", redirect.IPhone)
			http.Redirect(w, r, redirect.IPhone, 302)
			return
		}
		matched = regexp.MustCompile("iPad").MatchString(userAgent)
		if matched {
			log.Println("ipad", redirect.IPad)
			http.Redirect(w, r, redirect.IPad, 302)
			return
		}
		matched = regexp.MustCompile("BlackBerry").MatchString(userAgent)
		if matched {
			log.Println("bb", redirect.BlackBerry)
			http.Redirect(w, r, redirect.BlackBerry, 302)
			return
		}
		matched = regexp.MustCompile("IEMobile").MatchString(userAgent)
		if matched {
			log.Println("wp", redirect.WindowsPhone)
			http.Redirect(w, r, redirect.WindowsPhone, 302)
			return
		}

		log.Println("unknown", redirect.Unknown)
		http.Redirect(w, r, redirect.Unknown, 302)
		return
	}
	log.Println("unmatched", config.Redirects[0].Unknown)
	http.Redirect(w, r, config.Redirects[0].Unknown, 302)
}

func main() {
	fh, err := os.Open("config.json")
	if err != nil {
		log.Fatal("opening config.json failed")
		return
	}
	defer fh.Close()
	configcontent, err := ioutil.ReadAll(fh)
	if err != nil {
		log.Fatal("reading config.json failed")
		return
	}

	if err = json.Unmarshal(configcontent, config); err != nil {
		log.Fatal("parsing config.json failed")
		return
	}

	http.HandleFunc("/", handler)
	log.Fatal(
		http.ListenAndServe(
			fmt.Sprintf("%s:%d", config.Address, config.Port),
			nil))
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"time"

	irukaLogger "github.com/bottlenose-inc/go-iruka/logger" // go-iruka bunyan-style logger package
	"github.com/bottlenose-inc/go-iruka/metrics"            // go-iruka Prometheus metrics package
	"github.com/codegangsta/cli"                            // CLI helper
	"github.com/prometheus/client_golang/prometheus"        // Prometheus client library
)

var (
	nsqdUrl              string
	scrapeInterval       int
	logger               *irukaLogger.Logger
	depthGaugeVec        *prometheus.GaugeVec
	inFlightGaugeVec     *prometheus.GaugeVec
	backendDepthGaugeVec *prometheus.GaugeVec
	timeoutGaugeVec      *prometheus.GaugeVec
	requeueGaugeVec      *prometheus.GaugeVec
	deferredGaugeVec     *prometheus.GaugeVec
	messageCountGaugeVec *prometheus.GaugeVec
	clientCountGaugeVec  *prometheus.GaugeVec
	channelCountGaugeVec *prometheus.GaugeVec
)

func main() {
	app := cli.NewApp()
	app.Version = "0.1.0"
	app.Name = "nsqd-prometheus-exporter"
	app.Usage = "Scrapes nsqd stats and serves them up as Prometheus metrics"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "nsqdUrl, n",
			Value:  "http://localhost:4151",
			Usage:  "URL of nsqd to export stats from",
			EnvVar: "NSQD_URL",
		},
		cli.StringFlag{
			Name:   "prometheusPort, pp",
			Value:  "30000",
			Usage:  "Port on which prometheus will expose metrics",
			EnvVar: "PROMETHEUS_PORT",
		},
		cli.StringFlag{
			Name:   "scrapeInterval, s",
			Value:  "5",
			Usage:  "How often (in seconds) nsqd stats should be scraped",
			EnvVar: "SCRAPE_INTERVAL",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "./nsqd-prometheus-exporter [options] run",
			Action: func(c *cli.Context) {
				// Initialize logger
				var err error
				logger, err = irukaLogger.NewLogger(app.Name + " v" + app.Version)
				if err != nil {
					log.Fatal("Unable to initialize go-iruka logger, exiting: " + err.Error())
				}

				// Set and validate configuration
				nsqdUrl = c.GlobalString("nsqdUrl")
				if nsqdUrl == "" {
					logger.Fatal("nsqdUrl not provided, exiting")
					os.Exit(1)
				}
				scrapeInterval = c.GlobalInt("scrapeInterval")
				if scrapeInterval < 1 {
					logger.Warning("Invalid scrape interval set, continuing with default (5s)")
					scrapeInterval = 5
				}

				// Initialize Prometheus metrics
				var emptyMap map[string]string
				labels := []string{"type", "topic", "paused", "channel"}
				// # HELP nsq_depth Queue depth
				// # TYPE nsq_depth gauge
				depthGaugeVec, _ = metrics.CreateGaugeVector("nsq_depth", "", "", "Queue depth", emptyMap, labels)
				// # HELP nsq_backend_depth Queue backend depth
				// # TYPE nsq_backend_depth gauge
				backendDepthGaugeVec, _ = metrics.CreateGaugeVector("nsq_backend_depth", "", "", "Queue backend depth", emptyMap, labels)
				// # HELP nsq_in_flight_count In flight count
				// # TYPE nsq_in_flight_count gauge
				inFlightGaugeVec, _ = metrics.CreateGaugeVector("nsq_in_flight_count", "", "", "In flight count", emptyMap, labels)
				// # HELP nsq_timeout_count Timeout count
				// # TYPE nsq_timeout_count gauge
				timeoutGaugeVec, _ = metrics.CreateGaugeVector("nsq_timeout_count", "", "", "Timeout count", emptyMap, labels)
				// # HELP nsq_requeue_count Requeue Count
				// # TYPE nsq_requeue_count gauge
				requeueGaugeVec, _ = metrics.CreateGaugeVector("nsq_requeue_count", "", "", "Requeue Count", emptyMap, labels)
				// # HELP nsq_deferred_count Deferred count
				// # TYPE nsq_deferred_count gauge
				deferredGaugeVec, _ = metrics.CreateGaugeVector("nsq_deferred_count", "", "", "Deferred count", emptyMap, labels)
				// # HELP nsq_message_count Queue message count
				// # TYPE nsq_message_count gauge
				messageCountGaugeVec, _ = metrics.CreateGaugeVector("nsq_message_count", "", "", "Queue message count", emptyMap, labels)
				// # HELP nsq_client_count Number of clients
				// # TYPE nsq_client_count gauge
				clientCountGaugeVec, _ = metrics.CreateGaugeVector("nsq_client_count", "", "", "Number of clients", emptyMap, labels)
				// # HELP nsq_channel_count Number of channels
				// # TYPE nsq_channel_count gauge
				channelCountGaugeVec, _ = metrics.CreateGaugeVector("nsq_channel_count", "", "", "Number of channels", emptyMap, []string{"type", "topic", "paused"})

				go fetchAndSetStats()

				err = metrics.StartPrometheusMetricsServer(app.Name, logger, c.GlobalInt("prometheusPort"))
				if err != nil {
					os.Exit(1)
				}
			},
		},
	}

	app.Run(os.Args)
}

// fetchAndSetStats scrapes stats from nsqd and updates all the Prometheus metrics on the provided interval.
func fetchAndSetStats() {
	for {
		// Fetch stats
		stats, err := getNsqdStats(nsqdUrl)
		if err != nil {
			logger.Fatal("Error scraping stats from nsqd: " + err.Error())
			os.Exit(1)
		}

		// Loop through topics and set metrics
		for _, topic := range stats.Topics {
			paused := "false"
			if topic.Paused {
				paused = "true"
			}
			depthGaugeVec.WithLabelValues("topic", topic.Name, paused, "").Set(float64(topic.Depth))
			backendDepthGaugeVec.WithLabelValues("topic", topic.Name, paused, "").Set(float64(topic.BackendDepth))
			channelCountGaugeVec.WithLabelValues("topic", topic.Name, paused).Set(float64(len(topic.Channels)))

			// Loop through a topic's channels and set metrics
			for _, channel := range topic.Channels {
				paused = "false"
				if channel.Paused {
					paused = "true"
				}
				depthGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.Depth))
				backendDepthGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.BackendDepth))
				inFlightGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.InFlightCount))
				timeoutGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.TimeoutCount))
				requeueGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.RequeueCount))
				deferredGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.DeferredCount))
				messageCountGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.MessageCount))
				clientCountGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(len(channel.Clients)))
			}
		}

		// Scrape every scrapeInterval
		time.Sleep(time.Duration(scrapeInterval) * time.Second)
	}
}
<commit_msg>bump default scrape interval to 30s<commit_after>package main

import (
	"log"
	"os"
	"time"

	irukaLogger "github.com/bottlenose-inc/go-iruka/logger" // go-iruka bunyan-style logger package
	"github.com/bottlenose-inc/go-iruka/metrics"            // go-iruka Prometheus metrics package
	"github.com/codegangsta/cli"                            // CLI helper
	"github.com/prometheus/client_golang/prometheus"        // Prometheus client library
)

var (
	nsqdUrl              string
	scrapeInterval       int
	logger               *irukaLogger.Logger
	depthGaugeVec        *prometheus.GaugeVec
	inFlightGaugeVec     *prometheus.GaugeVec
	backendDepthGaugeVec *prometheus.GaugeVec
	timeoutGaugeVec      *prometheus.GaugeVec
	requeueGaugeVec      *prometheus.GaugeVec
	deferredGaugeVec     *prometheus.GaugeVec
	messageCountGaugeVec *prometheus.GaugeVec
	clientCountGaugeVec  *prometheus.GaugeVec
	channelCountGaugeVec *prometheus.GaugeVec
)

func main() {
	app := cli.NewApp()
	app.Version = "0.1.0"
	app.Name = "nsqd-prometheus-exporter"
	app.Usage = "Scrapes nsqd stats and serves them up as Prometheus metrics"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "nsqdUrl, n",
			Value:  "http://localhost:4151",
			Usage:  "URL of nsqd to export stats from",
			EnvVar: "NSQD_URL",
		},
		cli.StringFlag{
			Name:   "prometheusPort, pp",
			Value:  "30000",
			Usage:  "Port on which prometheus will expose metrics",
			EnvVar: "PROMETHEUS_PORT",
		},
		cli.StringFlag{
			Name:   "scrapeInterval, s",
			Value:  "30",
			Usage:  "How often (in seconds) nsqd stats should be scraped",
			EnvVar: "SCRAPE_INTERVAL",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "./nsqd-prometheus-exporter [options] run",
			Action: func(c *cli.Context) {
				// Initialize logger
				var err error
				logger, err = irukaLogger.NewLogger(app.Name + " v" + app.Version)
				if err != nil {
					log.Fatal("Unable to initialize go-iruka logger, exiting: " + err.Error())
				}

				// Set and validate configuration
				nsqdUrl = c.GlobalString("nsqdUrl")
				if nsqdUrl == "" {
					logger.Fatal("nsqdUrl not provided, exiting")
					os.Exit(1)
				}
				scrapeInterval = c.GlobalInt("scrapeInterval")
				if scrapeInterval < 1 {
					logger.Warning("Invalid scrape interval set, continuing with default (30s)")
					scrapeInterval = 30
				}

				// Initialize Prometheus metrics
				var emptyMap map[string]string
				labels := []string{"type", "topic", "paused", "channel"}
				// # HELP nsq_depth Queue depth
				// # TYPE nsq_depth gauge
				depthGaugeVec, _ = metrics.CreateGaugeVector("nsq_depth", "", "", "Queue depth", emptyMap, labels)
				// # HELP nsq_backend_depth Queue backend depth
				// # TYPE nsq_backend_depth gauge
				backendDepthGaugeVec, _ = metrics.CreateGaugeVector("nsq_backend_depth", "", "", "Queue backend depth", emptyMap, labels)
				// # HELP nsq_in_flight_count In flight count
				// # TYPE nsq_in_flight_count gauge
				inFlightGaugeVec, _ = metrics.CreateGaugeVector("nsq_in_flight_count", "", "", "In flight count", emptyMap, labels)
				// # HELP nsq_timeout_count Timeout count
				// # TYPE nsq_timeout_count gauge
				timeoutGaugeVec, _ = metrics.CreateGaugeVector("nsq_timeout_count", "", "", "Timeout count", emptyMap, labels)
				// # HELP nsq_requeue_count Requeue Count
				// # TYPE nsq_requeue_count gauge
				requeueGaugeVec, _ = metrics.CreateGaugeVector("nsq_requeue_count", "", "", "Requeue Count", emptyMap, labels)
				// # HELP nsq_deferred_count Deferred count
				// # TYPE nsq_deferred_count gauge
				deferredGaugeVec, _ = metrics.CreateGaugeVector("nsq_deferred_count", "", "", "Deferred count", emptyMap, labels)
				// # HELP nsq_message_count Queue message count
				// # TYPE nsq_message_count gauge
				messageCountGaugeVec, _ = metrics.CreateGaugeVector("nsq_message_count", "", "", "Queue message count", emptyMap, labels)
				// # HELP nsq_client_count Number of clients
				// # TYPE nsq_client_count gauge
				clientCountGaugeVec, _ = metrics.CreateGaugeVector("nsq_client_count", "", "", "Number of clients", emptyMap, labels)
				// # HELP nsq_channel_count Number of channels
				// # TYPE nsq_channel_count gauge
				channelCountGaugeVec, _ = metrics.CreateGaugeVector("nsq_channel_count", "", "", "Number of channels", emptyMap, []string{"type", "topic", "paused"})

				go fetchAndSetStats()

				err = metrics.StartPrometheusMetricsServer(app.Name, logger, c.GlobalInt("prometheusPort"))
				if err != nil {
					os.Exit(1)
				}
			},
		},
	}

	app.Run(os.Args)
}

// fetchAndSetStats scrapes stats from nsqd and updates all the Prometheus metrics on the provided interval.
func fetchAndSetStats() {
	for {
		// Fetch stats
		stats, err := getNsqdStats(nsqdUrl)
		if err != nil {
			logger.Fatal("Error scraping stats from nsqd: " + err.Error())
			os.Exit(1)
		}

		// Loop through topics and set metrics
		for _, topic := range stats.Topics {
			paused := "false"
			if topic.Paused {
				paused = "true"
			}
			depthGaugeVec.WithLabelValues("topic", topic.Name, paused, "").Set(float64(topic.Depth))
			backendDepthGaugeVec.WithLabelValues("topic", topic.Name, paused, "").Set(float64(topic.BackendDepth))
			channelCountGaugeVec.WithLabelValues("topic", topic.Name, paused).Set(float64(len(topic.Channels)))

			// Loop through a topic's channels and set metrics
			for _, channel := range topic.Channels {
				paused = "false"
				if channel.Paused {
					paused = "true"
				}
				depthGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.Depth))
				backendDepthGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.BackendDepth))
				inFlightGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.InFlightCount))
				timeoutGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.TimeoutCount))
				requeueGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.RequeueCount))
				deferredGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.DeferredCount))
				messageCountGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(channel.MessageCount))
				clientCountGaugeVec.WithLabelValues("channel", channel.Name, paused, channel.Name).Set(float64(len(channel.Clients)))
			}
		}

		// Scrape every scrapeInterval
		time.Sleep(time.Duration(scrapeInterval) * time.Second)
	}
}
<|endoftext|>


<commit_before>//TODO: improve the code

package main

import (
	"fmt"
	"github.com/franleplant/juliaSets/utils"
	"image"
	"image/color"
	"image/draw"
	"math/cmplx"
)

const (
	N       = 500
	MIN_x   = float64(-1.0)
	c       = c7
	c1      = -0.4 + 0.6i //nice
	c2      = -0.285 + 0.1i
	c3      = (1 - 1.618033987) + 0.0i //Golden ratio
	c4      = -0.8 + 0.156i            //nice
	c5      = 0.279 + 0.0i             //really nice
	c6      = 0 + 0i                   //circle
	c7      = -2 + 0i
	PHASE   = 150.0
	K_COLOR = 5.0
)

func fz1(z complex128) complex128 {
	return cmplx.Pow(z, 2) + 0.279 + 0.0i
}
func main() {
	getColor := utils.GetColorFactory(K_COLOR, PHASE)
	escapeTime(fz1, getColor, N, MIN_x)
}

// Sufficiently big enough matrix
type CMatrix [5000][5000]complex128

type fzType func(z complex128) complex128

var fzi = fz1

var m CMatrix
var z *complex128

func escapeTime(fz fzType, getColor utils.GetColorType, N int, MIN_x float64) {
	const (
		MAX_ITERATIONS = 3000
		ER             = 1
	)

	var count int
	var r, g, b uint8
	var (
		M      = N
		MAX_x  = -MIN_x
		MIN_y  = MIN_x
		MAX_y  = MAX_x
		STEP_x = (MAX_x - MIN_y) / float64(M)
		STEP_y = (MAX_y - MIN_y) / float64(N)
	)

	img := image.NewRGBA(image.Rect(0, 0, M, N))

	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			z = &m[i][j]
			*z = complex(MIN_x+float64(j)*STEP_x, MAX_y-float64(i)*STEP_y)
			//fmt.Println(*z)

			for count = 0; count < MAX_ITERATIONS; count++ {
				//*z = cmplx.Pow(*z, 2) + c
				*z = fzi(*z)
				if cmplx.Abs(*z) > ER {
					//fmt.Printf("count %v color %v ", count, (math.Mod(PHASE*float64(count), 255.0))/255.0)
					break
				}
			}

			if count == MAX_ITERATIONS {
				fmt.Println("Max Iterations reached")
			}

			r, g, b = getColor(count)
			//fmt.Printf("r %v g %v b %v \n", r, g, b)

			draw.Draw(img, image.Rect(j, i, j+1, i+1), &image.Uniform{color.RGBA{r, g, b, 255}}, image.ZP, draw.Src)
		}
	}

	utils.SaveImg(img)
}
<commit_msg>keep refactoring<commit_after>//TODO: improve the code

package main

import (
	"github.com/franleplant/juliaSets/alg"
	"github.com/franleplant/juliaSets/utils"
	"math/cmplx"
)

const (
	N       = 500
	MIN_x   = float64(-1.0)
	c       = c7
	c1      = -0.4 + 0.6i //nice
	c2      = -0.285 + 0.1i
	c3      = (1 - 1.618033987) + 0.0i //Golden ratio
	c4      = -0.8 + 0.156i            //nice
	c5      = 0.279 + 0.0i             //really nice
	c6      = 0 + 0i                   //circle
	c7      = -2 + 0i
	PHASE   = 150.0
	K_COLOR = 5.0
)

func fz1(z complex128) complex128 {
	return cmplx.Pow(z, 2) + 0.279 + 0.0i
}
func main() {
	getColor := utils.GetColorFactory(K_COLOR, PHASE)
	alg.EscapeTime(fz1, getColor, N, MIN_x)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"
)

var (
	file    = flag.String("file", "", "Source file (required)")
	out     = flag.String("out", "", "Output file or /dev/null")
	in      = flag.String("in", "", "Input file")
	tape    = flag.String("tape", "static", "Tape type: static or dynamic")
	noop    = flag.Bool("noop", false, "Disable optimization")
	dump    = flag.Bool("dump", false, "Dump AST")
	show    = flag.Int("show", 0, "Dump # tape cells around last position")
	profile = flag.String("profile", "", "Write CPU profile to file")
)

func output(out, in string) (io.ReadWriter, error) {
	var err error
	var r io.Reader
	var w io.Writer

	if out != "" {
		w, err = os.Create(out)
		if err != nil {
			return nil, err
		}
	} else {
		w = os.Stdout
	}

	if in != "" {
		r, err = os.Open(in)
		if err != nil {
			return nil, err
		}
	} else {
		r = os.Stdin
	}
	return struct {
		io.Reader
		io.Writer
	}{r, w}, nil
}

var storage = map[string]func(io.ReadWriter) Storage{
	"static":  NewStaticTape,
	"dynamic": NewDynamicTape,
}

func main() {
	flag.Parse()

	if *profile != "" {
		f, err := os.Create(*profile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *file == "" {
		flag.Usage()
		return
	}

	program, err := ParseFile(*file)
	if err != nil {
		log.Fatal(err)
	}

	if !*noop {
		program = Optimize(program)
	}

	if *dump {
		fmt.Println(program)
		return
	}

	if st, ok := storage[*tape]; ok {
		o, err := output(*out, *in)
		if err != nil {
			log.Fatal(err)
		}
		s := st(o)
		Execute(program, s)
		if *show > 0 {
			cels, pos := s.Dump()
			from := pos - *show/2
			if from < 0 {
				from = 0
			}
			to := pos + *show/2
			if to > len(cels) {
				to = len(cels)
			}
			log.Println("From", from, "to", to, cels[from:to])
		}
	} else {
		flag.Usage()
		return
	}
}
<commit_msg>Sort options by type<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"runtime/pprof"
)

var (
	file    = flag.String("file", "", "Source file (required)")
	in      = flag.String("in", "", "Input file")
	out     = flag.String("out", "", "Output file or /dev/null")
	profile = flag.String("profile", "", "Write CPU profile to file")
	tape    = flag.String("tape", "static", "Tape type: static or dynamic")
	dump    = flag.Bool("dump", false, "Dump AST and terminate")
	noop    = flag.Bool("noop", false, "Disable optimization")
	show    = flag.Int("show", 0, "Dump # tape cells around last position")
)

func output(out, in string) (io.ReadWriter, error) {
	var err error
	var r io.Reader
	var w io.Writer

	if out != "" {
		w, err = os.Create(out)
		if err != nil {
			return nil, err
		}
	} else {
		w = os.Stdout
	}

	if in != "" {
		r, err = os.Open(in)
		if err != nil {
			return nil, err
		}
	} else {
		r = os.Stdin
	}
	return struct {
		io.Reader
		io.Writer
	}{r, w}, nil
}

var storage = map[string]func(io.ReadWriter) Storage{
	"static":  NewStaticTape,
	"dynamic": NewDynamicTape,
}

func main() {
	flag.Parse()

	if *profile != "" {
		f, err := os.Create(*profile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *file == "" {
		flag.Usage()
		return
	}

	program, err := ParseFile(*file)
	if err != nil {
		log.Fatal(err)
	}

	if !*noop {
		program = Optimize(program)
	}

	if *dump {
		fmt.Println(program)
		return
	}

	if st, ok := storage[*tape]; ok {
		o, err := output(*out, *in)
		if err != nil {
			log.Fatal(err)
		}
		s := st(o)
		Execute(program, s)
		if *show > 0 {
			cels, pos := s.Dump()
			from := pos - *show/2
			if from < 0 {
				from = 0
			}
			to := pos + *show/2
			if to > len(cels) {
				to = len(cels)
			}
			log.Println("From", from, "to", to, cels[from:to])
		}
	} else {
		flag.Usage()
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"container/list"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"sync"
	"time"
	"github.com/Vivena/babelweb2/parser"
	"github.com/Vivena/babelweb2/ws"
)

type connectslice []string

var myconnectlist connectslice
var Listconduct = list.New()
var Quitmain = make(chan struct{}, 2)

func (i *connectslice) String() string {
	return fmt.Sprintf("%s", *i)
}
func (i *connectslice) Set(value string) error {
	fmt.Printf("%s\n", value)
	*i = append(*i, value)
	return nil
}

func flagsInit(bwPort *string) int {

	flag.Var(&myconnectlist, "hp",
		"list of hostnames and portnums (shorthand)")
	flag.Var(&myconnectlist, "hostport", "liste of hostnames and portnums")

	flag.StringVar(bwPort, "b", ":8080", "babelweb Port (shorthand)")
	flag.StringVar(bwPort, "bwport", ":8080", "babelweb Port")
	flag.Parse()

	return len(myconnectlist)
}

func connection(updates chan parser.BabelUpdate,
	wg *sync.WaitGroup, bwPort *string) {
	var node string
	node = "[::1]:33123"
	var lenArg = flagsInit(bwPort)
	if lenArg == 0 {
		go ConnectionNode(updates, node, wg, Quitmain)
	} else {
		connectGroup(updates, wg)
	}
}

func ConnectionNode(updates chan parser.BabelUpdate, node string,
	wg *sync.WaitGroup, quit chan struct{}) {
	var conn net.Conn
	var err error

	wg.Add(1)
	defer wg.Done()

	for {
		exit := true
		select {
		case _, q := <-quit:
			if !q {
				return
			}
		default:
			log.Println("	Trying ", node)
			for exit {
				select {
				case _, q := <-quit:
					if !q {
						return
					}
				default:
					conn, err = net.Dial("tcp6", node)
					if err != nil {
						log.Println(err)
						time.Sleep(time.Second * 5)
					} else {
						exit = false
					}
				}
			}
			log.Println("	Connected to", node)
			fmt.Fprintf(conn, "monitor\n")
			r := bufio.NewReader(conn)
			s := parser.NewScanner(r)

			bd := parser.NewBabelDesc()
			bd.Fill(s)
			ws.AddDesc(bd)
			err := ws.Db[bd.Id()].Bd.Listen(s, updates)

			conn.Close()
			log.Println("Connection closed")
			if err != nil {
				log.Println(err)
				return
			}
			ws.Db[bd.Id()].M.Lock()
			err = ws.Db[bd.Id()].Bd.Clean(updates)
			ws.Db[bd.Id()].M.Unlock()
			if err != nil {
				log.Println(err)
				return
			}
		}
	}
}

/*-----    connection to multiple routers    ----*/
func connectGroup(updates chan parser.BabelUpdate, wgGroup *sync.WaitGroup) {
	var quitgroup = make(chan struct{}, 2)

	for i := 0; i < len(myconnectlist); i++ {
		go ConnectionNode(updates, myconnectlist[i],
			wgGroup, quitgroup)
	}
}

func main() {
	ws.Init()
	defer close(Quitmain)
	log.Println("	--------launching server--------")
	var bwPort string
	var wg sync.WaitGroup

	updates := make(chan parser.BabelUpdate, ws.ChanelSize)
	defer close(updates)

	connection(updates, &wg, &bwPort)
	bcastGrp := ws.NewListenerGroup()
	go ws.MCUpdates(updates, bcastGrp, &wg)
	ws := ws.Handler(bcastGrp)
	http.Handle("/", http.FileServer(http.Dir("static/")))
	http.Handle("/style.css", http.FileServer(http.Dir("static/css/")))
	http.Handle("/initialize.js", http.FileServer(http.Dir("static/js")))
	http.Handle("/d3/d3.js", http.FileServer(http.Dir("static/js")))
	http.Handle("/ws", ws)

	err := http.ListenAndServe(bwPort, nil)
	if err != nil {
		log.Println(err)
		return
	}
	wg.Wait()
}
<commit_msg>Add absolute path to static folder.<commit_after>package main

import (
	"bufio"
	"container/list"
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"sync"
	"time"
	"github.com/Vivena/babelweb2/parser"
	"github.com/Vivena/babelweb2/ws"
)

type connectslice []string

var myconnectlist connectslice
var Listconduct = list.New()
var Quitmain = make(chan struct{}, 2)

func (i *connectslice) String() string {
	return fmt.Sprintf("%s", *i)
}
func (i *connectslice) Set(value string) error {
	fmt.Printf("%s\n", value)
	*i = append(*i, value)
	return nil
}

func flagsInit(bwPort *string) int {

	flag.Var(&myconnectlist, "hp",
		"list of hostnames and portnums (shorthand)")
	flag.Var(&myconnectlist, "hostport", "liste of hostnames and portnums")

	flag.StringVar(bwPort, "b", ":8080", "babelweb Port (shorthand)")
	flag.StringVar(bwPort, "bwport", ":8080", "babelweb Port")
	flag.Parse()

	return len(myconnectlist)
}

func connection(updates chan parser.BabelUpdate,
	wg *sync.WaitGroup, bwPort *string) {
	var node string
	node = "[::1]:33123"
	var lenArg = flagsInit(bwPort)
	if lenArg == 0 {
		go ConnectionNode(updates, node, wg, Quitmain)
	} else {
		connectGroup(updates, wg)
	}
}

func ConnectionNode(updates chan parser.BabelUpdate, node string,
	wg *sync.WaitGroup, quit chan struct{}) {
	var conn net.Conn
	var err error

	wg.Add(1)
	defer wg.Done()

	for {
		exit := true
		select {
		case _, q := <-quit:
			if !q {
				return
			}
		default:
			log.Println("	Trying ", node)
			for exit {
				select {
				case _, q := <-quit:
					if !q {
						return
					}
				default:
					conn, err = net.Dial("tcp6", node)
					if err != nil {
						log.Println(err)
						time.Sleep(time.Second * 5)
					} else {
						exit = false
					}
				}
			}
			log.Println("	Connected to", node)
			fmt.Fprintf(conn, "monitor\n")
			r := bufio.NewReader(conn)
			s := parser.NewScanner(r)

			bd := parser.NewBabelDesc()
			bd.Fill(s)
			ws.AddDesc(bd)
			err := ws.Db[bd.Id()].Bd.Listen(s, updates)

			conn.Close()
			log.Println("Connection closed")
			if err != nil {
				log.Println(err)
				return
			}
			ws.Db[bd.Id()].M.Lock()
			err = ws.Db[bd.Id()].Bd.Clean(updates)
			ws.Db[bd.Id()].M.Unlock()
			if err != nil {
				log.Println(err)
				return
			}
		}
	}
}

/*-----    connection to multiple routers    ----*/
func connectGroup(updates chan parser.BabelUpdate, wgGroup *sync.WaitGroup) {
	var quitgroup = make(chan struct{}, 2)

	for i := 0; i < len(myconnectlist); i++ {
		go ConnectionNode(updates, myconnectlist[i],
			wgGroup, quitgroup)
	}
}

func main() {
	ws.Init()
	defer close(Quitmain)
	log.Println("	--------launching server--------")
	var bwPort string
	var wg sync.WaitGroup

	updates := make(chan parser.BabelUpdate, ws.ChanelSize)
	defer close(updates)

	connection(updates, &wg, &bwPort)
	bcastGrp := ws.NewListenerGroup()
	go ws.MCUpdates(updates, bcastGrp, &wg)
	ws := ws.Handler(bcastGrp)
	static := os.Getenv("GOPATH") +
		"/src/github.com/Vivena/babelweb2/static/"
	http.Handle("/", http.FileServer(http.Dir(static)))
	http.Handle("/style.css", http.FileServer(http.Dir(static + "css/")))
	http.Handle("/initialize.js", http.FileServer(http.Dir(static + "js/")))
	http.Handle("/d3/d3.js", http.FileServer(http.Dir(static + "js/")))
	http.Handle("/ws", ws)

	err := http.ListenAndServe(bwPort, nil)
	if err != nil {
		log.Println(err)
		return
	}
	wg.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/nlopes/slack"
	"github.com/rprakashg/foodtruck-slack-bot/seattlefoodtruck"
)

const s3Bucket = "https://s3-us-west-2.amazonaws.com/seattlefoodtruck-uploads-prod/"

func main() {
	token := os.Getenv("SLACK_TOKEN")
	api := slack.New(token)
	rtm := api.NewRTM()
	go rtm.ManageConnection()

Loop:
	for {
		select {
		case msg := <-rtm.IncomingEvents:
			switch ev := msg.Data.(type) {
			case *slack.ConnectedEvent:
				fmt.Println("Connection Count: ", ev.ConnectionCount)

			case *slack.MessageEvent:
				fmt.Printf("Incoming message: %v\n", ev)
				info := rtm.GetInfo()
				prefix := fmt.Sprintf("<@%s> ", info.User.ID)

				//only respond if @mention user is same as bot user id, we don't want to respond to other messages on channel
				if ev.User != info.User.ID && strings.HasPrefix(ev.Text, prefix) {
					respond(rtm, ev, prefix)
				}

			case *slack.RTMError:
				fmt.Printf("Error: %s\n", ev.Error())

			case *slack.InvalidAuthEvent:
				fmt.Printf("Invalid credentials")
				break Loop

			default:
				//Take no action
			}
		}
	}
}
func respond(rtm *slack.RTM, msg *slack.MessageEvent, prefix string) {
	text := msg.Text
	text = strings.TrimPrefix(text, prefix)
	text = strings.TrimSpace(text)
	text = strings.ToLower(text)

	if text == "help" {
		response := fmt.Sprintf("%s: \n", "*You can ask me*")
		response += fmt.Sprintf("%s \n", "• *show neighborhoods* - to see neighborhoods served")
		response += fmt.Sprintf("%s \n", "• *show locations in <neighborhood>* - to see food truck locations in a neighborhood")
		response += fmt.Sprintf("%s \n", "• *show trucks at <location>* - to see food trucks at a location")

		rtm.SendMessage(rtm.NewOutgoingMessage(response, msg.Channel))
	} else if text == "show neighborhoods" {
		showNeighborhoods(rtm, msg.Channel)
	} else if strings.Contains(text, "show locations") {
		showLocations(rtm, text, msg.Channel)
	} else if strings.Contains(text, "show trucks") {
		showTrucks(rtm, text, msg.Channel)
	} else {
		rtm.SendMessage(rtm.NewOutgoingMessage("Sorry I cannot help you with this, please try help to see things you can ask me", msg.Channel))
	}
}
func showNeighborhoods(rtm *slack.RTM, channel string) {
	var message string
	p, _ := seattlefoodtruck.NewProxy("https://www.seattlefoodtruck.com")
	resp, err := p.GetNeighborhoods()
	if err != nil {
		rtm.SendMessage(rtm.NewOutgoingMessage(err.Error(), channel))
		return
	}
	if len(resp.Neighborhoods) == 0 {
		message = fmt.Sprintf("%s \n", "No Neighborhoods found")
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	//show all neighborhoods
	message = fmt.Sprintf("%s \n", "*You can find food trucks in following neighborhoods*")
	for _, n := range resp.Neighborhoods {
		message += fmt.Sprintf("• %s \n", n.ID)
	}
	rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
}

func showLocations(rtm *slack.RTM, text string, channel string) {
	var message string
	tokens := strings.Split(text, "in")
	if len(tokens) < 2 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing Neighborhood", channel))
		return
	}
	neighborhood := strings.TrimSpace(tokens[1])
	if len(neighborhood) == 0 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing neighborhood", channel))
		return
	}
	p, _ := seattlefoodtruck.NewProxy("https://www.seattlefoodtruck.com")
	lr := seattlefoodtruck.LocationRequest{
		Page:         1,
		Neighborhood: neighborhood,
	}
	resp, err := p.GetLocations(&lr)
	if err != nil {
		rtm.SendMessage(rtm.NewOutgoingMessage(err.Error(), channel))
		return
	}
	if len(resp.Locations) == 0 {
		message = fmt.Sprintf("No locations found at %s neighborhood \n", neighborhood)
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	message = fmt.Sprintf("%s \n", "*You can find food trucks in following locations*")
	for _, l := range resp.Locations {
		message += fmt.Sprintf("• %s - %v \n", l.Name, l.UID)
	}
	rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
}

func showTrucks(rtm *slack.RTM, text string, channel string) {
	var message string
	//extract location id from text
	tokens := strings.Split(text, "at")
	if len(tokens) < 2 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing location", channel))
		return
	}
	locString := strings.TrimSpace(tokens[1])
	if len(locString) == 0 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing location", channel))
		return
	}
	location, _ := strconv.Atoi(locString)
	p, _ := seattlefoodtruck.NewProxy("https://www.seattlefoodtruck.com")
	req := seattlefoodtruck.NewLocationEventsRequest(location, 1)
	resp, err := p.GetLocationEvents(&req)
	if err != nil {
		rtm.SendMessage(rtm.NewOutgoingMessage(err.Error(), channel))
		return
	}
	if len(resp.Events) == 0 {
		message = fmt.Sprintf("No events at %v", locString)
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	index := find(resp.Events, filterByStartDate)
	if index == -1 {
		message = fmt.Sprintf("No food trucks found at %v", locString)
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	event := resp.Events[0]
	st, _ := time.Parse(time.RFC3339, event.StartTime)
	et, _ := time.Parse(time.RFC3339, event.EndTime)
	_, m, d := st.Date()
	message = fmt.Sprintf("%v %v %v - %v \n", m, d, st.Hour(), et.Hour())

	for _, b := range event.Bookings {
		message += fmt.Sprintf("*%v* (%s) %v \n", b.Truck.Name,
			strings.Join(b.Truck.FoodCategories, ","), s3Bucket+b.Truck.FeaturedPhoto)
	}
	//send message to channel
	rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
}

//returns the index of found event for today's date, if none returns -1
func find(events []seattlefoodtruck.Event, f func(seattlefoodtruck.Event) bool) int {
	for i, e := range events {
		if f(e) {
			return i
		}
	}
	return -1
}

// used to filter by event start date
func filterByStartDate(event seattlefoodtruck.Event) bool {
	ct := time.Now()
	y1, m1, d1 := ct.Date()
	//parse start time
	st, _ := time.Parse(time.RFC3339, event.StartTime)
	y2, m2, d2 := st.Date()
	if y1 == y2 && m1 == m2 && d1 == d2 {
		return true
	}
	return false
}
<commit_msg>minor fix<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/nlopes/slack"
	"github.com/rprakashg/foodtruck-slack-bot/seattlefoodtruck"
)

const s3Bucket = "https://s3-us-west-2.amazonaws.com/seattlefoodtruck-uploads-prod/"

func main() {
	token := os.Getenv("SLACK_TOKEN")
	api := slack.New(token)
	rtm := api.NewRTM()
	go rtm.ManageConnection()

Loop:
	for {
		select {
		case msg := <-rtm.IncomingEvents:
			switch ev := msg.Data.(type) {
			case *slack.ConnectedEvent:
				fmt.Println("Connection Count: ", ev.ConnectionCount)

			case *slack.MessageEvent:
				fmt.Printf("Incoming message: %v\n", ev)
				info := rtm.GetInfo()
				prefix := fmt.Sprintf("<@%s> ", info.User.ID)

				//only respond if @mention user is same as bot user id, we don't want to respond to other messages on channel
				if ev.User != info.User.ID && strings.HasPrefix(ev.Text, prefix) {
					respond(rtm, ev, prefix)
				}

			case *slack.RTMError:
				fmt.Printf("Error: %s\n", ev.Error())

			case *slack.InvalidAuthEvent:
				fmt.Printf("Invalid credentials")
				break Loop

			default:
				//Take no action
			}
		}
	}
}
func respond(rtm *slack.RTM, msg *slack.MessageEvent, prefix string) {
	text := msg.Text
	text = strings.TrimPrefix(text, prefix)
	text = strings.TrimSpace(text)
	text = strings.ToLower(text)

	if text == "help" {
		response := fmt.Sprintf("%s: \n", "*You can ask me*")
		response += fmt.Sprintf("%s \n", "• *show neighborhoods* - to see neighborhoods served")
		response += fmt.Sprintf("%s \n", "• *show locations in <neighborhood>* - to see food truck locations in a neighborhood")
		response += fmt.Sprintf("%s \n", "• *show trucks at <location>* - to see food trucks at a location")

		rtm.SendMessage(rtm.NewOutgoingMessage(response, msg.Channel))
	} else if text == "show neighborhoods" {
		showNeighborhoods(rtm, msg.Channel)
	} else if strings.Contains(text, "show locations") {
		showLocations(rtm, text, msg.Channel)
	} else if strings.Contains(text, "show trucks") {
		showTrucks(rtm, text, msg.Channel)
	} else {
		rtm.SendMessage(rtm.NewOutgoingMessage("Sorry I cannot help you with this, please try help to see things you can ask me", msg.Channel))
	}
}
func showNeighborhoods(rtm *slack.RTM, channel string) {
	var message string
	p, _ := seattlefoodtruck.NewProxy("https://www.seattlefoodtruck.com")
	resp, err := p.GetNeighborhoods()
	if err != nil {
		rtm.SendMessage(rtm.NewOutgoingMessage(err.Error(), channel))
		return
	}
	if len(resp.Neighborhoods) == 0 {
		message = fmt.Sprintf("%s \n", "No Neighborhoods found")
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	//show all neighborhoods
	message = fmt.Sprintf("%s \n", "*You can find food trucks in following neighborhoods*")
	for _, n := range resp.Neighborhoods {
		message += fmt.Sprintf("• %s \n", n.ID)
	}
	rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
}

func showLocations(rtm *slack.RTM, text string, channel string) {
	var message string
	tokens := strings.Split(text, "in")
	if len(tokens) < 2 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing Neighborhood", channel))
		return
	}
	neighborhood := strings.TrimSpace(tokens[1])
	if len(neighborhood) == 0 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing neighborhood", channel))
		return
	}
	p, _ := seattlefoodtruck.NewProxy("https://www.seattlefoodtruck.com")
	lr := seattlefoodtruck.LocationRequest{
		Page:         1,
		Neighborhood: neighborhood,
	}
	resp, err := p.GetLocations(&lr)
	if err != nil {
		rtm.SendMessage(rtm.NewOutgoingMessage(err.Error(), channel))
		return
	}
	if len(resp.Locations) == 0 {
		message = fmt.Sprintf("No locations found at %s neighborhood \n", neighborhood)
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	message = fmt.Sprintf("%s \n", "*You can find food trucks in following locations*")
	for _, l := range resp.Locations {
		message += fmt.Sprintf("• %s - %v \n", l.Name, l.UID)
	}
	rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
}

func showTrucks(rtm *slack.RTM, text string, channel string) {
	var message string
	//extract location id from text
	tokens := strings.Split(text, "at")
	if len(tokens) < 2 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing location", channel))
		return
	}
	locString := strings.TrimSpace(tokens[1])
	if len(locString) == 0 {
		rtm.SendMessage(rtm.NewOutgoingMessage("Missing location", channel))
		return
	}
	location, _ := strconv.Atoi(locString)
	p, _ := seattlefoodtruck.NewProxy("https://www.seattlefoodtruck.com")
	req := seattlefoodtruck.NewLocationEventsRequest(location, 1)
	resp, err := p.GetLocationEvents(&req)
	if err != nil {
		rtm.SendMessage(rtm.NewOutgoingMessage(err.Error(), channel))
		return
	}
	if len(resp.Events) == 0 {
		message = fmt.Sprintf("No events at %v", locString)
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	index := find(resp.Events, filterByStartDate)
	if index == -1 {
		message = fmt.Sprintf("No food trucks found at %v", locString)
		rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
		return
	}
	event := resp.Events[index]
	st, _ := time.Parse(time.RFC3339, event.StartTime)
	et, _ := time.Parse(time.RFC3339, event.EndTime)
	_, m, d := st.Date()
	message = fmt.Sprintf("%v %v %v - %v \n", m, d, st.Hour(), et.Hour())

	for _, b := range event.Bookings {
		message += fmt.Sprintf("*%v* (%s) %v \n", b.Truck.Name,
			strings.Join(b.Truck.FoodCategories, ","), s3Bucket+b.Truck.FeaturedPhoto)
	}
	//send message to channel
	rtm.SendMessage(rtm.NewOutgoingMessage(message, channel))
}

//returns the index of found event for today's date, if none returns -1
func find(events []seattlefoodtruck.Event, f func(seattlefoodtruck.Event) bool) int {
	for i, e := range events {
		if f(e) {
			return i
		}
	}
	return -1
}

// used to filter by event start date
func filterByStartDate(event seattlefoodtruck.Event) bool {
	ct := time.Now()
	y1, m1, d1 := ct.Date()
	//parse start time
	st, _ := time.Parse(time.RFC3339, event.StartTime)
	y2, m2, d2 := st.Date()
	if y1 == y2 && m1 == m2 && d1 == d2 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/fsouza/go-dockerclient"
)

var serfElector *serfMasterElector
var actionTimer *time.Timer
var cleanupTimer *time.Timer
var configTimer *time.Timer
var dockerClient *docker.Client
var cfg *config

// #### HELPERS ####

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

func appendIfMissing(slice []string, s string) []string {
	for _, e := range slice {
		if e == s {
			return slice
		}
	}
	return append(slice, s)
}

// #### DOCKER ####

func getImages(dangling bool) []docker.APIImages {
	images, err := dockerClient.ListImages(false)
	orFail(err)

	response := []docker.APIImages{}

	for _, v := range images {
		if dangling {
			if len(v.RepoTags) == 1 && v.RepoTags[0] == "<none>:<none>" {
				response = append(response, v)
			}
		} else {
			if len(v.RepoTags) != 1 || v.RepoTags[0] != "<none>:<none>" {
				response = append(response, v)
			}
		}
	}

	return response
}

func cleanDangling() {
	images := getImages(true)
	for _, v := range images {
		log.Printf("Removing dangling image: %s", v.ID)
		dockerClient.RemoveImage(v.ID)
	}
}

func refreshImages() {
	for _, v := range *cfg {
		log.Printf("Refreshing repo %s:%s...", v.Image, v.Tag)
		err := dockerClient.PullImage(docker.PullImageOptions{
			Repository: v.Image,
			Tag:        v.Tag,
		}, docker.AuthConfiguration{})
		orFail(err)
	}
}

// #### MAIN ####

func main() {
	serfAddress := flag.String("serfAddress", "127.0.0.1:7373", "Address of the serf agent to connect to")
	//configURL := flag.String("configURL", "", "URL to the config file for direct download")
	connectPort := flag.Int("port", 2221, "Port to connect to the docker daemon")
	flag.Parse()

	serfElector = newSerfMasterElector()
	go serfElector.Run(*serfAddress)

	// Create a timer but stop it immediately for later usage
	actionTimer = time.NewTimer(time.Second * 60)
	actionTimer.Stop()

	// Cleanup is done by each node individually, not only by the master
	cleanupTimer = time.NewTimer(time.Second * 30)

	configTimer = time.NewTimer(time.Second * 1)

	var err error
	dockerClient, err = docker.NewClient(fmt.Sprintf("tcp://127.0.0.1:%d", *connectPort))
	orFail(err)

	for {
		select {
		case masterState := <-serfElector.MasterState:
			if masterState {
				// Give the program 60s before taking actions
				actionTimer.Reset(time.Second * 60)
				log.Print("Enabled actions")
			} else {
				actionTimer.Stop()
				log.Print("Disabled actions")
			}
		case <-actionTimer.C:
			log.Print("Action-Tick!")

			//refreshImages()
			//cleanDangling()

			actionTimer.Reset(time.Second * 300)
		case <-cleanupTimer.C:
			log.Print("Cleanup-Tick!")

			refreshImages()
			cleanDangling()

			cleanupTimer.Reset(time.Minute * 30)
		case <-configTimer.C:
			log.Print("Loading config...")

			cfg = readConfig("./config.yaml")

			configTimer.Reset(time.Minute * 10)
		}
	}

}
<commit_msg>Added container management<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/fsouza/go-dockerclient"
)

var serfElector *serfMasterElector
var actionTimer *time.Timer
var cleanupTimer *time.Timer
var configTimer *time.Timer
var dockerClient *docker.Client
var cfg *config

// #### HELPERS ####

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

func orLog(err error) {
	if err != nil {
		log.Print(err)
	}
}

func appendIfMissing(slice []string, s string) []string {
	for _, e := range slice {
		if e == s {
			return slice
		}
	}
	return append(slice, s)
}

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

// #### DOCKER ####

func getImages(dangling bool) []docker.APIImages {
	images, err := dockerClient.ListImages(false)
	orFail(err)

	response := []docker.APIImages{}

	for _, v := range images {
		if dangling {
			if len(v.RepoTags) == 1 && v.RepoTags[0] == "<none>:<none>" {
				response = append(response, v)
			}
		} else {
			if len(v.RepoTags) != 1 || v.RepoTags[0] != "<none>:<none>" {
				response = append(response, v)
			}
		}
	}

	return response
}

func cleanDangling() {
	images := getImages(true)
	for _, v := range images {
		log.Printf("Removing dangling image: %s", v.ID)
		dockerClient.RemoveImage(v.ID)
	}
}

func refreshImages() {
	for _, v := range *cfg {
		log.Printf("Refreshing repo %s:%s...", v.Image, v.Tag)
		err := dockerClient.PullImage(docker.PullImageOptions{
			Repository: v.Image,
			Tag:        v.Tag,
		}, docker.AuthConfiguration{})
		orLog(err)
	}
}

func bootContainer(name string, cfg containerConfig) {
	newcfg := &docker.Config{
		AttachStdin:  false,
		AttachStdout: true,
		AttachStderr: true,
		Image:        strings.Join([]string{cfg.Image, cfg.Tag}, ":"),
		Env:          cfg.Environment,
	}
	log.Printf("Creating container %s", name)
	container, err := dockerClient.CreateContainer(docker.CreateContainerOptions{
		Name:   name,
		Config: newcfg,
	})
	orLog(err)
	if err != nil {
		return
	}

	hostConfig := docker.HostConfig{
		Binds:        cfg.Volumes,
		Privileged:   false,
		PortBindings: make(map[docker.Port][]docker.PortBinding),
	}

	for _, v := range cfg.Ports {
		s := strings.Split(v.Local, ":")
		hostConfig.PortBindings[docker.Port(v.Container)] = []docker.PortBinding{docker.PortBinding{
			HostIp:   s[0],
			HostPort: s[1],
		}}
	}

	log.Printf("Starting container %s", container.Name)
	dockerClient.StartContainer(container.Name, &hostConfig)
}

func listRunningContainers() ([]docker.APIContainers, error) {
	containers, err := dockerClient.ListContainers(docker.ListContainersOptions{
		All: false,
	})
	orLog(err)
	return containers, err
}

func ensureContainers() {
	// TODO: Refactor, too long.
	expectedRunning := []string{}
	currentRunning, err := listRunningContainers()
	orLog(err)
	if err != nil {
		return
	}
	for name, containerCfg := range *cfg {
		if stringInSlice(serfElector.MyName, containerCfg.Hosts) || stringInSlice("ALL", containerCfg.Hosts) {
			expectedRunning = append(expectedRunning, name)
		}
	}

	// Stop containers not expected to be running
	for _, v := range currentRunning {
		allowed := false
		for _, n := range v.Names {
			if stringInSlice(strings.Trim(n, "/"), expectedRunning) {
				allowed = true
			}
		}
		if !allowed {
			log.Printf("Stopping container %s as it is not expected to be running.", v.ID)
			err := dockerClient.StopContainer(v.ID, 5)
			orFail(err)
			time.Sleep(time.Second * 5)
		}
	}

	// Stop containers who are of deprecated images
	currentRunning, _ = listRunningContainers()
	images := getImages(false)
	for _, n := range expectedRunning {
		repoName := strings.Join([]string{(*cfg)[n].Image, (*cfg)[n].Tag}, ":")
		currentImageID := "0"
		for _, i := range images {
			if stringInSlice(repoName, i.RepoTags) {
				currentImageID = i.ID
			}
		}
		if currentImageID == "0" {
			log.Printf("Found no image ID for repo %s", strings.Join([]string{(*cfg)[n].Image, (*cfg)[n].Tag}, ":"))
			continue
		}
		for _, v := range currentRunning {
			if stringInSlice(fmt.Sprintf("/%s", n), v.Names) && !strings.HasPrefix(currentImageID, v.Image) && v.Image != repoName {
				log.Printf("Image: %s Current: %s", v.Image, currentImageID)
				log.Printf("Stopping deprecated container %s", v.ID)
				err := dockerClient.StopContainer(v.ID, 5)
				orFail(err)
				time.Sleep(time.Second * 5)
				log.Printf("Removing deprecated container %s", v.ID)
				dockerClient.RemoveContainer(docker.RemoveContainerOptions{
					ID: v.ID,
				})
			}
		}
	}

	// Start expected containers
	currentRunning, _ = listRunningContainers()
	runningNames := []string{}
	for _, v := range currentRunning {
		for _, n := range v.Names {
			runningNames = append(runningNames, strings.Trim(n, "/"))
		}
	}
	for _, n := range expectedRunning {
		if !stringInSlice(n, runningNames) {
			bootContainer(n, (*cfg)[n])
		}
	}
}

func cleanContainers() {
	runningContainers, err := dockerClient.ListContainers(docker.ListContainersOptions{
		All: true,
	})
	orLog(err)
	if err != nil {
		return
	}

	for _, v := range runningContainers {
		if strings.HasPrefix(v.Status, "Exited") {
			log.Printf("Removing stopped container %s", v.ID)
			err := dockerClient.RemoveContainer(docker.RemoveContainerOptions{
				ID: v.ID,
			})
			orLog(err)
		}
	}
}

// #### MAIN ####

func main() {
	serfAddress := flag.String("serfAddress", "127.0.0.1:7373", "Address of the serf agent to connect to")
	//configURL := flag.String("configURL", "", "URL to the config file for direct download")
	connectPort := flag.Int("port", 2221, "Port to connect to the docker daemon")
	flag.Parse()

	serfElector = newSerfMasterElector()
	go serfElector.Run(*serfAddress)

	// Create a timer but stop it immediately for later usage
	actionTimer = time.NewTimer(time.Second * 60)
	actionTimer.Stop()

	// Cleanup is done by each node individually, not only by the master
	cleanupTimer = time.NewTimer(time.Second * 30)

	configTimer = time.NewTimer(time.Second * 1)

	var err error
	dockerClient, err = docker.NewClient(fmt.Sprintf("tcp://127.0.0.1:%d", *connectPort))
	orFail(err)

	for {
		select {
		case masterState := <-serfElector.MasterState:
			if masterState {
				// Give the program 60s before taking actions
				actionTimer.Reset(time.Second * 60)
				log.Print("Enabled actions")
			} else {
				actionTimer.Stop()
				log.Print("Disabled actions")
			}
		case <-actionTimer.C:
			log.Print("Action-Tick!")

			refreshImages()
			ensureContainers()

			actionTimer.Reset(time.Second * 300)
		case <-cleanupTimer.C:
			log.Print("Cleanup-Tick!")

			cleanContainers()
			cleanDangling()

			cleanupTimer.Reset(time.Minute * 30)
		case <-configTimer.C:
			log.Print("Loading config...")

			cfg = readConfig("./config.yaml")

			configTimer.Reset(time.Minute * 10)
		}
	}

}
<|endoftext|>