<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
)

const Version = "0.0.1"

func handlePackets(ps *gopacket.PacketSource, img *image.NRGBA, num uint) {
	var count uint
	var y int
	for packet := range ps.Packets() {
		var i int
		var j int
		count++
		if count > num {
			break
		}
		elements := packet.Data()
		for i = 0; i+3 <= len(elements); i += 3 {
			img.Set(j, y, color.NRGBA{
				R: uint8(elements[i] & 255),
				G: uint8(elements[i+1] & 255),
				B: uint8(elements[i+2] & 255),
				A: 255})
			j++
		}
		switch len(elements) - i {
		case 2:
			img.Set(j, y, color.NRGBA{
				R: uint8(elements[i] & 255),
				G: uint8(elements[i+1] & 255),
				B: uint8(0),
				A: 255})
			break
		case 1:
			img.Set(j, y, color.NRGBA{
				R: uint8(elements[i] & 255),
				G: uint8(0 & 255),
				B: uint8(0 & 255),
				A: 255})
			break
		default:
		}
		y++
	}
	return
}

func availableInterfaces() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}

	for _, device := range devices {
		if len(device.Addresses) == 0 {
			continue
		}
		fmt.Println("Interface: ", device.Name)
		for _, address := range device.Addresses {
			fmt.Println("   IP address:  ", address.IP)
			fmt.Println("   Subnet mask: ", address.Netmask)
		}
		fmt.Println("")
	}
}

func main() {
	var err error
	var handle *pcap.Handle

	dev := flag.String("interface", "", "Choose an interface for online processing")
	file := flag.String("file", "", "Choose a file for offline processing")
	filter := flag.String("filter", "", "Set a specific filter")
	lst := flag.Bool("list_interfaces", false, "List available interfaces")
	vers := flag.Bool("version", false, "Show version")
	help := flag.Bool("help", false, "Show help")
	num := flag.Uint("count", 10, "Number of packets to process")
	output := flag.String("output", "image.png", "Name of the resulting image")
	flag.Parse()

	if flag.NFlag() < 1 {
		flag.PrintDefaults()
		return
	}

	if *lst {
		availableInterfaces()
		return
	}

	if *vers {
		fmt.Println("Version:", Version)
		return
	}

	if *help {
		flag.PrintDefaults()
		return
	}

	if len(*dev) > 0 {
		handle, err = pcap.OpenLive(*dev, 4096, true, pcap.BlockForever)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else if len(*file) > 0 {
		handle, err = pcap.OpenOffline(*file)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else {
		fmt.Println("Source is missing")
		return
	}
	defer handle.Close()

	img := image.NewNRGBA(image.Rect(0, 0, 512, int(*num)))

	if len(*filter) != 0 {
		err = handle.SetBPFFilter(*filter)
		if err != nil {
			log.Fatal(err, "\tInvalid filter: ", *filter)
			os.Exit(1)
		}
	}

	packetSource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
	packetSource.DecodeOptions = gopacket.Lazy

	handlePackets(packetSource, img, *num)

	f, err := os.Create(*output)
	if err != nil {
		log.Fatal(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		log.Fatal(err)
	}

	if err := f.Close(); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Minor improvement<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
)

const Version = "0.0.1"

func handlePackets(ps *gopacket.PacketSource, img *image.NRGBA, num uint) {
	var count uint
	var y int
	for packet := range ps.Packets() {
		var i int
		var j int
		count++
		if count > num {
			break
		}
		elements := packet.Data()
		if len(elements) == 0 {
			continue
		}
		for i = 0; i+3 <= len(elements); i += 3 {
			img.Set(j, y, color.NRGBA{
				R: uint8(elements[i] & 255),
				G: uint8(elements[i+1] & 255),
				B: uint8(elements[i+2] & 255),
				A: 255})
			j++
		}
		switch len(elements) - i {
		case 2:
			img.Set(j, y, color.NRGBA{
				R: uint8(elements[i] & 255),
				G: uint8(elements[i+1] & 255),
				B: uint8(0),
				A: 255})
			break
		case 1:
			img.Set(j, y, color.NRGBA{
				R: uint8(elements[i] & 255),
				G: uint8(0 & 255),
				B: uint8(0 & 255),
				A: 255})
			break
		default:
		}
		y++
	}
	return
}

func availableInterfaces() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}

	for _, device := range devices {
		if len(device.Addresses) == 0 {
			continue
		}
		fmt.Println("Interface: ", device.Name)
		for _, address := range device.Addresses {
			fmt.Println("   IP address:  ", address.IP)
			fmt.Println("   Subnet mask: ", address.Netmask)
		}
		fmt.Println("")
	}
}

func main() {
	var err error
	var handle *pcap.Handle

	dev := flag.String("interface", "", "Choose an interface for online processing")
	file := flag.String("file", "", "Choose a file for offline processing")
	filter := flag.String("filter", "", "Set a specific filter")
	lst := flag.Bool("list_interfaces", false, "List available interfaces")
	vers := flag.Bool("version", false, "Show version")
	help := flag.Bool("help", false, "Show help")
	num := flag.Uint("count", 10, "Number of packets to process")
	output := flag.String("output", "image.png", "Name of the resulting image")
	flag.Parse()

	if flag.NFlag() < 1 {
		flag.PrintDefaults()
		return
	}

	if *lst {
		availableInterfaces()
		return
	}

	if *vers {
		fmt.Println("Version:", Version)
		return
	}

	if *help {
		flag.PrintDefaults()
		return
	}

	if len(*dev) > 0 {
		handle, err = pcap.OpenLive(*dev, 4096, true, pcap.BlockForever)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else if len(*file) > 0 {
		handle, err = pcap.OpenOffline(*file)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else {
		fmt.Println("Source is missing")
		return
	}
	defer handle.Close()

	img := image.NewNRGBA(image.Rect(0, 0, 512, int(*num)))

	if len(*filter) != 0 {
		err = handle.SetBPFFilter(*filter)
		if err != nil {
			log.Fatal(err, "\tInvalid filter: ", *filter)
			os.Exit(1)
		}
	}

	packetSource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
	packetSource.DecodeOptions = gopacket.Lazy

	handlePackets(packetSource, img, *num)

	f, err := os.Create(*output)
	if err != nil {
		log.Fatal(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		log.Fatal(err)
	}

	if err := f.Close(); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package monitor

import (
	"strings"
	"testing"
	"time"

	"github.com/influxdb/influxdb"
	"github.com/influxdb/influxdb/influxql"
	"github.com/influxdb/influxdb/meta"
)

// Test that a registered stats client results in the correct SHOW STATS output.
func Test_RegisterStats(t *testing.T) {
	monitor := openMonitor(t)
	executor := &StatementExecutor{Monitor: monitor}

	// Register stats without tags.
	statMap := influxdb.NewStatistics("foo", "foo", nil)
	statMap.Add("bar", 1)
	statMap.AddFloat("qux", 2.4)
	json := executeShowStatsJSON(t, executor)
	if !strings.Contains(json, `"columns":["bar","qux"],"values":[[1,2.4]]`) || !strings.Contains(json, `"name":"foo"`) {
		t.Fatalf("SHOW STATS response incorrect, got: %s\n", json)
	}

	// Register a client with tags.
	statMap = influxdb.NewStatistics("bar", "baz", map[string]string{"proto": "tcp"})
	statMap.Add("bar", 1)
	statMap.AddFloat("qux", 2.4)
	json = executeShowStatsJSON(t, executor)
	if !strings.Contains(json, `"columns":["bar","qux"],"values":[[1,2.4]]`) ||
		!strings.Contains(json, `"name":"baz"`) ||
		!strings.Contains(json, `"proto":"tcp"`) {
		t.Fatalf("SHOW STATS response incorrect, got: %s\n", json)

	}
}

type mockMetastore struct{}

func (m *mockMetastore) ClusterID() uint64                                     { return 1, nil }
func (m *mockMetastore) IsLeader() bool                                        { return true }
func (m *mockMetastore) SetDefaultRetentionPolicy(database, name string) error { return nil }
func (m *mockMetastore) DropRetentionPolicy(database, name string) error       { return nil }
func (m *mockMetastore) CreateDatabase(name string) (*meta.DatabaseInfo, error) {
	return nil, nil
}
func (m *mockMetastore) CreateRetentionPolicy(database string, rpi *meta.RetentionPolicyInfo) (*meta.RetentionPolicyInfo, error) {
	return nil, nil
}

func openMonitor(t *testing.T) *Monitor {
	monitor := New(NewConfig())
	monitor.MetaStore = &mockMetastore{}
	err := monitor.Open()
	if err != nil {
		t.Fatalf("failed to open monitor: %s", err.Error())
	}
	return monitor
}

func executeShowStatsJSON(t *testing.T, s *StatementExecutor) string {
	r := s.ExecuteStatement(&influxql.ShowStatsStatement{})
	b, err := r.MarshalJSON()
	if err != nil {
		t.Fatalf("failed to decode SHOW STATS response: %s", err.Error())
	}
	return string(b)
}
<commit_msg>Fix monitor tests<commit_after>package monitor

import (
	"strings"
	"testing"

	"github.com/influxdb/influxdb"
	"github.com/influxdb/influxdb/influxql"
	"github.com/influxdb/influxdb/services/meta"
)

// Test that a registered stats client results in the correct SHOW STATS output.
func Test_RegisterStats(t *testing.T) {
	monitor := openMonitor(t)
	executor := &StatementExecutor{Monitor: monitor}

	// Register stats without tags.
	statMap := influxdb.NewStatistics("foo", "foo", nil)
	statMap.Add("bar", 1)
	statMap.AddFloat("qux", 2.4)
	json := executeShowStatsJSON(t, executor)
	if !strings.Contains(json, `"columns":["bar","qux"],"values":[[1,2.4]]`) || !strings.Contains(json, `"name":"foo"`) {
		t.Fatalf("SHOW STATS response incorrect, got: %s\n", json)
	}

	// Register a client with tags.
	statMap = influxdb.NewStatistics("bar", "baz", map[string]string{"proto": "tcp"})
	statMap.Add("bar", 1)
	statMap.AddFloat("qux", 2.4)
	json = executeShowStatsJSON(t, executor)
	if !strings.Contains(json, `"columns":["bar","qux"],"values":[[1,2.4]]`) ||
		!strings.Contains(json, `"name":"baz"`) ||
		!strings.Contains(json, `"proto":"tcp"`) {
		t.Fatalf("SHOW STATS response incorrect, got: %s\n", json)

	}
}

type mockMetaClient struct{}

func (m *mockMetaClient) ClusterID() uint64                                     { return 1 }
func (m *mockMetaClient) IsLeader() bool                                        { return true }
func (m *mockMetaClient) SetDefaultRetentionPolicy(database, name string) error { return nil }
func (m *mockMetaClient) DropRetentionPolicy(database, name string) error       { return nil }
func (m *mockMetaClient) CreateDatabase(name string) (*meta.DatabaseInfo, error) {
	return nil, nil
}
func (m *mockMetaClient) CreateRetentionPolicy(database string, rpi *meta.RetentionPolicyInfo) (*meta.RetentionPolicyInfo, error) {
	return nil, nil
}

func openMonitor(t *testing.T) *Monitor {
	monitor := New(NewConfig())
	monitor.MetaClient = &mockMetaClient{}
	err := monitor.Open()
	if err != nil {
		t.Fatalf("failed to open monitor: %s", err.Error())
	}
	return monitor
}

func executeShowStatsJSON(t *testing.T, s *StatementExecutor) string {
	r := s.ExecuteStatement(&influxql.ShowStatsStatement{})
	b, err := r.MarshalJSON()
	if err != nil {
		t.Fatalf("failed to decode SHOW STATS response: %s", err.Error())
	}
	return string(b)
}
<|endoftext|>


<commit_before>package main

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

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/newrelic/sidecar/catalog"
	"github.com/newrelic/sidecar/haproxy"
	"gopkg.in/alecthomas/kingpin.v1"
)

const (
	RELOAD_BUFFER    = 20
	// A new service usually comes in as three events.
	// By 5 seconds it's usually alive.
	RELOAD_HOLD_DOWN = 5 * time.Second
)

var (
	proxy        *haproxy.HAproxy
	stateLock    sync.Mutex
	reloadChan   chan time.Time
	currentState *catalog.ServicesState
)

type CliOpts struct {
	ConfigFile *string
}

type ApiError struct {
	Error string `json:"error"`
}

type ApiMessage struct {
	Message string `json:"message"`
}

func exitWithError(err error, message string) {
	if err != nil {
		log.Fatal("%s: %s", message, err.Error())
	}
}

func parseCommandLine() *CliOpts {
	var opts CliOpts
	opts.ConfigFile = kingpin.Flag("config-file", "The config file to use").Short('f').Default("haproxy-api.toml").String()
	kingpin.Parse()
	return &opts
}

func run(command string) error {
	cmd := exec.Command("/bin/bash", "-c", command)
	err := cmd.Run()
	if err != nil {
		log.Errorf("Error running '%s': %s", command, err.Error())
	}

	return err
}

func healthHandler(response http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()
	response.Header().Set("Content-Type", "application/json")

	err := run("test -f " + proxy.PidFile + " && ps aux `cat " + proxy.PidFile + "`")
	if err != nil {
		message, _ := json.Marshal(ApiError{"No HAproxy running!"})
		response.WriteHeader(http.StatusInternalServerError)
		response.Write(message)
		return
	}

	message, _ := json.Marshal(ApiMessage{"Healthy!"})
	response.Write(message)
	return
}

func updateHandler(response http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()
	response.Header().Set("Content-Type", "application/json")

	bytes, err := ioutil.ReadAll(req.Body)
	if err != nil {
		message, _ := json.Marshal(ApiError{err.Error()})
		response.Write(message)
		response.WriteHeader(http.StatusInternalServerError)
		return
	}

	state, err := catalog.Decode(bytes)
	if err != nil {
		response.WriteHeader(http.StatusInternalServerError)
		return
	}

	updateState(state)
}

func processUpdates() {
	for {
		// Batch up to RELOAD_BUFFER number updates into a
		// single update.
		first := <-reloadChan
		pending := len(reloadChan)

		writeAndReload(currentState)

		// We just flushed the most recent state, dump all the
		// pending items up to that point.
		var reload time.Time
		for i := 0; i < pending; i++ {
			reload = <-reloadChan
		}

		if first.Before(reload) {
			log.Info("Skipped %d messages between %s and %s", pending, first, reload)
		}

		// Don't notify more frequently than every RELOAD_HOLD_DOWN period. When a
		// deployment rolls across the cluster it can trigger a bunch of groupable
		// updates.
		log.Debug("Holding down...")
		time.Sleep(RELOAD_HOLD_DOWN)
	}
}

func writeAndReload(state *catalog.ServicesState) {
	log.Info("Updating HAproxy")
	proxy.WriteAndReload(state)
}

func updateState(state *catalog.ServicesState) {
	stateLock.Lock()
	defer stateLock.Unlock()
	currentState = state
	reloadChan <- time.Now().UTC()
}

func fetchState(url string) error {
	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		return err
	}

	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	state, err := catalog.Decode(bytes)
	if err != nil {
		return err
	}

	writeAndReload(state)

	return nil
}

func serveHttp(listenIp string, listenPort int) {
	listenStr := fmt.Sprintf("%s:%d", listenIp, listenPort)

	log.Infof("Starting up on %s", listenStr)
	router := mux.NewRouter()

	router.HandleFunc("/update", updateHandler).Methods("POST")
	router.HandleFunc("/health", healthHandler).Methods("GET")
	http.Handle("/", handlers.LoggingHandler(os.Stdout, router))

	err := http.ListenAndServe(listenStr, nil)
	if err != nil {
		log.Fatalf("Can't start http server: %s", err.Error())
	}
}

func main() {
	opts := parseCommandLine()
	config := parseConfig(*opts.ConfigFile)

	proxy = config.HAproxy

	reloadChan = make(chan time.Time, RELOAD_BUFFER)

	log.Info("Fetching initial state on startup...")
	err := fetchState(config.Sidecar.StateUrl)
	if err != nil {
		log.Errorf("Failed to fetch state from '%s'... continuing in hopes someone will post it", config.Sidecar.StateUrl)
	} else {
		log.Info("Successfully retrieved state")
	}

	go processUpdates()

	serveHttp(config.HAproxyApi.BindIP, config.HAproxyApi.BindPort)

	close(reloadChan)
}
<commit_msg>Bump up reload buffer size for busier sites.<commit_after>package main

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

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/newrelic/sidecar/catalog"
	"github.com/newrelic/sidecar/haproxy"
	"gopkg.in/alecthomas/kingpin.v1"
)

const (
	RELOAD_BUFFER    = 256
	// A new service usually comes in as three events.
	// By 5 seconds it's usually alive.
	RELOAD_HOLD_DOWN = 5 * time.Second
)

var (
	proxy        *haproxy.HAproxy
	stateLock    sync.Mutex
	reloadChan   chan time.Time
	currentState *catalog.ServicesState
)

type CliOpts struct {
	ConfigFile *string
}

type ApiError struct {
	Error string `json:"error"`
}

type ApiMessage struct {
	Message string `json:"message"`
}

func exitWithError(err error, message string) {
	if err != nil {
		log.Fatal("%s: %s", message, err.Error())
	}
}

func parseCommandLine() *CliOpts {
	var opts CliOpts
	opts.ConfigFile = kingpin.Flag("config-file", "The config file to use").Short('f').Default("haproxy-api.toml").String()
	kingpin.Parse()
	return &opts
}

func run(command string) error {
	cmd := exec.Command("/bin/bash", "-c", command)
	err := cmd.Run()
	if err != nil {
		log.Errorf("Error running '%s': %s", command, err.Error())
	}

	return err
}

func healthHandler(response http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()
	response.Header().Set("Content-Type", "application/json")

	err := run("test -f " + proxy.PidFile + " && ps aux `cat " + proxy.PidFile + "`")
	if err != nil {
		message, _ := json.Marshal(ApiError{"No HAproxy running!"})
		response.WriteHeader(http.StatusInternalServerError)
		response.Write(message)
		return
	}

	message, _ := json.Marshal(ApiMessage{"Healthy!"})
	response.Write(message)
	return
}

func updateHandler(response http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()
	response.Header().Set("Content-Type", "application/json")

	bytes, err := ioutil.ReadAll(req.Body)
	if err != nil {
		message, _ := json.Marshal(ApiError{err.Error()})
		response.Write(message)
		response.WriteHeader(http.StatusInternalServerError)
		return
	}

	state, err := catalog.Decode(bytes)
	if err != nil {
		response.WriteHeader(http.StatusInternalServerError)
		return
	}

	updateState(state)
}

func processUpdates() {
	for {
		// Batch up to RELOAD_BUFFER number updates into a
		// single update.
		first := <-reloadChan
		pending := len(reloadChan)

		writeAndReload(currentState)

		// We just flushed the most recent state, dump all the
		// pending items up to that point.
		var reload time.Time
		for i := 0; i < pending; i++ {
			reload = <-reloadChan
		}

		if first.Before(reload) {
			log.Infof("Skipped %d messages between %s and %s", pending, first, reload)
		}

		// Don't notify more frequently than every RELOAD_HOLD_DOWN period. When a
		// deployment rolls across the cluster it can trigger a bunch of groupable
		// updates.
		log.Debug("Holding down...")
		time.Sleep(RELOAD_HOLD_DOWN)
	}
}

func writeAndReload(state *catalog.ServicesState) {
	log.Info("Updating HAproxy")
	proxy.WriteAndReload(state)
}

func updateState(state *catalog.ServicesState) {
	stateLock.Lock()
	defer stateLock.Unlock()
	currentState = state
	reloadChan <- time.Now().UTC()
}

func fetchState(url string) error {
	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		return err
	}

	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	state, err := catalog.Decode(bytes)
	if err != nil {
		return err
	}

	writeAndReload(state)

	return nil
}

func serveHttp(listenIp string, listenPort int) {
	listenStr := fmt.Sprintf("%s:%d", listenIp, listenPort)

	log.Infof("Starting up on %s", listenStr)
	router := mux.NewRouter()

	router.HandleFunc("/update", updateHandler).Methods("POST")
	router.HandleFunc("/health", healthHandler).Methods("GET")
	http.Handle("/", handlers.LoggingHandler(os.Stdout, router))

	err := http.ListenAndServe(listenStr, nil)
	if err != nil {
		log.Fatalf("Can't start http server: %s", err.Error())
	}
}

func main() {
	opts := parseCommandLine()
	config := parseConfig(*opts.ConfigFile)

	proxy = config.HAproxy

	reloadChan = make(chan time.Time, RELOAD_BUFFER)

	log.Info("Fetching initial state on startup...")
	err := fetchState(config.Sidecar.StateUrl)
	if err != nil {
		log.Errorf("Failed to fetch state from '%s'... continuing in hopes someone will post it", config.Sidecar.StateUrl)
	} else {
		log.Info("Successfully retrieved state")
	}

	go processUpdates()

	serveHttp(config.HAproxyApi.BindIP, config.HAproxyApi.BindPort)

	close(reloadChan)
}
<|endoftext|>


<commit_before>package main

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

type TwiML struct {
	XMLName xml.Name `xml:"Response"`

	Say     string `xml:",omitempty"`
	Play    string `xml:",omitempty"`
	Message string `xml:",omitempty"`
}

func main() {

	http.HandleFunc("/", hello)
	http.HandleFunc("/twiml", twiml)
	http.HandleFunc("/sms", sms)
	//http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	http.ListenAndServe(":4567", nil)

}

type Request struct {
	Ok      bool
	Members []User
}

func sms(w http.ResponseWriter, r *http.Request) {
	// Set initial variables
	accountSid := os.Getenv("TWILIO_ACCOUNT_SID")
	authToken := os.Getenv("TWILIO_AUTH_TOKEN")
	urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json"
	r.ParseForm()
	text := r.PostForm["text"][0]
	bodyArray := strings.Fields(text)
	to_slack_number := bodyArray[0]
	slack_msg := strings.Join(bodyArray[1:], " ")
	fmt.Println(to_slack_number, slack_msg)
	v := url.Values{}
	v.Set("To", to_slack_number)
	v.Set("From", os.Getenv("TWILIO_NUMBER"))
	v.Set("Body", slack_msg)
	rb := *strings.NewReader(v.Encode())

	// Create client
	client := &http.Client{}

	req, _ := http.NewRequest("POST", urlStr, &rb)
	req.SetBasicAuth(accountSid, authToken)
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	// Make request
	resp, _ := client.Do(req)
	fmt.Println(resp.Status)
}

func twiml(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	body := r.PostForm["Body"][0]
	from := r.PostForm["From"][0]
	bodyArray := strings.Fields(body)
	bodyArray = append(bodyArray, from)
	slack_channel := "#working-on"
	slack_msg := strings.Join(bodyArray, " ")
	resp, _ := http.Post(os.Getenv("SLACK_WEARHACKS_WEBHOOK_URL"), "text/json", strings.NewReader("{\"text\": \""+slack_msg+"\", \"channel\" : \""+slack_channel+"\"}"))
	fmt.Println(resp.Status)
	msg := "Responding..."
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		msg = "Message successfully sent!!!"

	} else {
		msg = "Message NOT sent!!!"
	}
	twiml := TwiML{Message: msg}
	x, err := xml.Marshal(twiml)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/xml")
	w.Write(x)
}

func hello(res http.ResponseWriter, req *http.Request) {
	fmt.Println("Welcome to SlackMS!!!")
}

type User struct {
	Id        string
	Name      string
	Deleted   bool
	Color     string
	Profile   profile
	Is_Admin  bool
	Is_Owner  bool
	Has_2fa   bool
	Has_Files bool
}

type profile struct {
	First_Name string
	Last_Name  string
	Real_Name  string
	Email      string
	Skype      string
	Phone      string
	Image_24   string
	Image_32   string
	Image_48   string
	Image_72   string
	Image_192  string
}
<commit_msg>Use Port from environment variable<commit_after>package main

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

type TwiML struct {
	XMLName xml.Name `xml:"Response"`

	Say     string `xml:",omitempty"`
	Play    string `xml:",omitempty"`
	Message string `xml:",omitempty"`
}

func main() {

	http.HandleFunc("/", hello)
	http.HandleFunc("/twiml", twiml)
	http.HandleFunc("/sms", sms)
	http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	//http.ListenAndServe(":4567", nil)

}

type Request struct {
	Ok      bool
	Members []User
}

func sms(w http.ResponseWriter, r *http.Request) {
	// Set initial variables
	accountSid := os.Getenv("TWILIO_ACCOUNT_SID")
	authToken := os.Getenv("TWILIO_AUTH_TOKEN")
	urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json"
	r.ParseForm()
	text := r.PostForm["text"][0]
	bodyArray := strings.Fields(text)
	to_slack_number := bodyArray[0]
	slack_msg := strings.Join(bodyArray[1:], " ")
	fmt.Println(to_slack_number, slack_msg)
	v := url.Values{}
	v.Set("To", to_slack_number)
	v.Set("From", os.Getenv("TWILIO_NUMBER"))
	v.Set("Body", slack_msg)
	rb := *strings.NewReader(v.Encode())

	// Create client
	client := &http.Client{}

	req, _ := http.NewRequest("POST", urlStr, &rb)
	req.SetBasicAuth(accountSid, authToken)
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	// Make request
	resp, _ := client.Do(req)
	fmt.Println(resp.Status)
}

func twiml(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	body := r.PostForm["Body"][0]
	from := r.PostForm["From"][0]
	bodyArray := strings.Fields(body)
	bodyArray = append(bodyArray, from)
	slack_channel := "#working-on"
	slack_msg := strings.Join(bodyArray, " ")
	resp, _ := http.Post(os.Getenv("SLACK_WEARHACKS_WEBHOOK_URL"), "text/json", strings.NewReader("{\"text\": \""+slack_msg+"\", \"channel\" : \""+slack_channel+"\"}"))
	fmt.Println(resp.Status)
	msg := "Responding..."
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		msg = "Message successfully sent!!!"

	} else {
		msg = "Message NOT sent!!!"
	}
	twiml := TwiML{Message: msg}
	x, err := xml.Marshal(twiml)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/xml")
	w.Write(x)
}

func hello(res http.ResponseWriter, req *http.Request) {
	fmt.Println("Welcome to SlackMS!!!")
}

type User struct {
	Id        string
	Name      string
	Deleted   bool
	Color     string
	Profile   profile
	Is_Admin  bool
	Is_Owner  bool
	Has_2fa   bool
	Has_Files bool
}

type profile struct {
	First_Name string
	Last_Name  string
	Real_Name  string
	Email      string
	Skype      string
	Phone      string
	Image_24   string
	Image_32   string
	Image_48   string
	Image_72   string
	Image_192  string
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	_ "expvar"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	_ "net/http/pprof"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"code.google.com/p/gogoprotobuf/proto"

	"github.com/bradfitz/gomemcache/memcache"
	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
)

type zipper string

var Zipper zipper

var queryCache bytesCache
var findCache bytesCache

var timeFormats = []string{"15:04 20060102", "20060102", "01/02/06"}

// dateParamToEpoch turns a passed string parameter into an epoch we can send to the Zipper
func dateParamToEpoch(s string, d int64) string {

	if s == "" {
		// return the default if nothing was passed
		return strconv.Itoa(int(d))
	}

	// relative timestamp
	if s[0] == '-' {

		offset, err := intervalString(s[1:])
		if err != nil {
			return strconv.Itoa(int(d))
		}

		return strconv.Itoa(int(timeNow().Add(-time.Duration(offset) * time.Second).Unix()))
	}

	if s == "now" {
		return strconv.Itoa(int(timeNow().Unix()))
	}

	_, err := strconv.Atoi(s)
	if err == nil && len(s) > 8 {
		return s // We got a timestamp so returning it
	}

	if strings.Contains(s, "_") {
		s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
	}

	for _, format := range timeFormats {
		t, err := time.Parse(format, s)
		if err == nil {
			return strconv.Itoa(int(t.Unix()))
		}
	}
	return strconv.Itoa(int(d))
}

func intervalString(s string) (int32, error) {

	var j int

	for j < len(s) && s[j] >= '0' && s[j] <= '9' {
		j++
	}
	offsetStr, unitStr := s[:j], s[j:]

	var units int
	switch unitStr {
	case "s", "sec", "secs", "second", "seconds":
		units = 1
	case "min", "minute", "minutes":
		units = 60
	case "h", "hour", "hours":
		units = 60 * 60
	case "d", "day", "days":
		units = 24 * 60 * 60
	case "w", "week", "weeks":
		units = 7 * 24 * 60 * 60
	case "mon", "month", "months":
		units = 30 * 24 * 60 * 60
	case "y", "year", "years":
		units = 365 * 24 * 60 * 60
	default:
		return 0, errors.New("unknown time units")
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		return 0, err
	}

	return int32(offset * units), nil
}

// FIXME(dgryski): extract the http.Get + unproto code into its own function

func (z zipper) Find(metric string) (pb.GlobResponse, error) {

	u, _ := url.Parse(string(z) + "/metrics/find/")

	u.RawQuery = url.Values{
		"query":  []string{metric},
		"format": []string{"protobuf"},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Find: http.Get: %+v\n", err)
		return pb.GlobResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Find: ioutil.ReadAll: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	var pbresp pb.GlobResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Find: proto.Unmarshal: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	return pbresp, nil
}

func (z zipper) Render(metric, from, until string) (pb.FetchResponse, error) {

	u, _ := url.Parse(string(z) + "/render/")

	u.RawQuery = url.Values{
		"target": []string{metric},
		"format": []string{"protobuf"},
		"from":   []string{from},
		"until":  []string{until},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Render: http.Get: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Render: ioutil.ReadAll: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	var pbresp pb.FetchResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Render: proto.Unmarshal: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	return pbresp, nil
}

type limiter chan struct{}

func (l limiter) enter() { l <- struct{}{} }
func (l limiter) leave() { <-l }

var Limiter limiter

// for testing
var timeNow = time.Now

type graphitePoint struct {
	value float64
	t     int32
}

func (g graphitePoint) MarshalJSON() ([]byte, error) {
	// TODO(dgryski): fmt.Sprintf() is slow, use strconv.Append{Float,Int}
	if math.IsNaN(g.value) {
		return []byte(fmt.Sprintf("[null,%d]", g.t)), nil
	}
	return []byte(fmt.Sprintf("[%g,%d]", g.value, g.t)), nil
}

type jsonResponse struct {
	Target     string          `json:"target"`
	Datapoints []graphitePoint `json:"datapoints"`
}

func renderHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	targets := r.Form["target"]
	from := r.FormValue("from")
	until := r.FormValue("until")
	useCache := r.FormValue("noCache") == ""

	// make sure the cache key doesn't say noCache, because it will never hit
	r.Form.Del("noCache")

	cacheKey := r.Form.Encode()

	if response, ok := queryCache.get(cacheKey); useCache && ok {
		w.Header().Set("Content-Type", "application/json")
		w.Write(response)
		return
	}

	// normalize from and until values
	from = dateParamToEpoch(from, timeNow().Add(-24*time.Hour).Unix())
	until = dateParamToEpoch(until, timeNow().Unix())

	var results []*pb.FetchResponse

	for _, target := range targets {

		exp, e, err := parseExpr(target)
		if err != nil || e != "" {
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}

		metricMap := make(map[string][]*pb.FetchResponse)

		for _, metric := range exp.metrics() {

			var glob pb.GlobResponse
			var haveCacheData bool

			if response, ok := findCache.get(metric); useCache && ok {
				err := proto.Unmarshal(response, &glob)
				haveCacheData = err == nil
			}

			if !haveCacheData {
				var err error
				glob, err = Zipper.Find(metric)
				if err != nil {
					continue
				}
				b, err := proto.Marshal(&glob)
				if err == nil {
					findCache.set(metric, b)
				}
			}

			// For each metric returned in the Find response, query Render
			rch := make(chan *pb.FetchResponse, len(glob.GetMatches()))
			leaves := 0
			for _, m := range glob.GetMatches() {
				if !m.GetIsLeaf() {
					continue
				}
				leaves++
				Limiter.enter()
				go func(m *pb.GlobMatch) {
					var rptr *pb.FetchResponse
					r, err := Zipper.Render(m.GetPath(), from, until)
					if err == nil {
						rptr = &r
					}
					rch <- rptr
					Limiter.leave()
				}(m)
			}

			for i := 0; i < leaves; i++ {
				r := <-rch
				if r != nil {
					metricMap[metric] = append(metricMap[metric], r)
				}
			}
		}

		exprs := evalExpr(exp, metricMap)
		results = append(results, exprs...)
	}

	var jresults []jsonResponse

	for _, r := range results {
		if r == nil {
			log.Println("skipping nil result")
		}
		datapoints := make([]graphitePoint, 0, len(r.Values))
		t := *r.StartTime
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				v = math.NaN()
			}
			datapoints = append(datapoints, graphitePoint{value: v, t: t})
			t += *r.StepTime
		}
		jresults = append(jresults, jsonResponse{Target: r.GetName(), Datapoints: datapoints})
	}

	jout, err := json.Marshal(jresults)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	queryCache.set(cacheKey, jout)

	w.Header().Set("Content-Type", "application/json")
	w.Write(jout)
}

func main() {

	z := flag.String("z", "", "zipper")
	port := flag.Int("p", 8080, "port")
	l := flag.Int("l", 20, "concurrency limit")
	mc := flag.String("mc", "", "comma separated memcached server list")

	flag.Parse()

	if *z == "" {
		log.Fatal("no zipper (-z) provided")
	}

	if p := os.Getenv("PORT"); p != "" {
		*port, _ = strconv.Atoi(p)
	}

	Limiter = make(chan struct{}, *l)

	if *z == "" {
		log.Fatal("no zipper provided")
	}

	if _, err := url.Parse(*z); err != nil {
		log.Fatal("unable to parze zipper:", err)
	}

	log.Println("using zipper", *z)

	if *mc != "" {
		servers := strings.Split(*mc, ",")
		queryCache = &memcachedCache{client: memcache.New(servers...)}
		findCache = &memcachedCache{client: memcache.New(servers...)}
	} else {
		queryCache = &expireCache{cache: make(map[string]cacheElement)}
		go queryCache.(*expireCache).cleaner()

		findCache = &expireCache{cache: make(map[string]cacheElement)}
		go findCache.(*expireCache).cleaner()
	}

	Zipper = zipper(*z)

	http.HandleFunc("/render/", renderHandler)

	log.Println("listening on port", *port)
	log.Fatalln(http.ListenAndServe(":"+strconv.Itoa(*port), nil))

}
<commit_msg>make GOMAXPROCS configurable from command line<commit_after>package main

import (
	"encoding/json"
	"errors"
	_ "expvar"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	_ "net/http/pprof"
	"net/url"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"code.google.com/p/gogoprotobuf/proto"

	"github.com/bradfitz/gomemcache/memcache"
	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
)

type zipper string

var Zipper zipper

var queryCache bytesCache
var findCache bytesCache

var timeFormats = []string{"15:04 20060102", "20060102", "01/02/06"}

// dateParamToEpoch turns a passed string parameter into an epoch we can send to the Zipper
func dateParamToEpoch(s string, d int64) string {

	if s == "" {
		// return the default if nothing was passed
		return strconv.Itoa(int(d))
	}

	// relative timestamp
	if s[0] == '-' {

		offset, err := intervalString(s[1:])
		if err != nil {
			return strconv.Itoa(int(d))
		}

		return strconv.Itoa(int(timeNow().Add(-time.Duration(offset) * time.Second).Unix()))
	}

	if s == "now" {
		return strconv.Itoa(int(timeNow().Unix()))
	}

	_, err := strconv.Atoi(s)
	if err == nil && len(s) > 8 {
		return s // We got a timestamp so returning it
	}

	if strings.Contains(s, "_") {
		s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
	}

	for _, format := range timeFormats {
		t, err := time.Parse(format, s)
		if err == nil {
			return strconv.Itoa(int(t.Unix()))
		}
	}
	return strconv.Itoa(int(d))
}

func intervalString(s string) (int32, error) {

	var j int

	for j < len(s) && s[j] >= '0' && s[j] <= '9' {
		j++
	}
	offsetStr, unitStr := s[:j], s[j:]

	var units int
	switch unitStr {
	case "s", "sec", "secs", "second", "seconds":
		units = 1
	case "min", "minute", "minutes":
		units = 60
	case "h", "hour", "hours":
		units = 60 * 60
	case "d", "day", "days":
		units = 24 * 60 * 60
	case "w", "week", "weeks":
		units = 7 * 24 * 60 * 60
	case "mon", "month", "months":
		units = 30 * 24 * 60 * 60
	case "y", "year", "years":
		units = 365 * 24 * 60 * 60
	default:
		return 0, errors.New("unknown time units")
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		return 0, err
	}

	return int32(offset * units), nil
}

// FIXME(dgryski): extract the http.Get + unproto code into its own function

func (z zipper) Find(metric string) (pb.GlobResponse, error) {

	u, _ := url.Parse(string(z) + "/metrics/find/")

	u.RawQuery = url.Values{
		"query":  []string{metric},
		"format": []string{"protobuf"},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Find: http.Get: %+v\n", err)
		return pb.GlobResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Find: ioutil.ReadAll: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	var pbresp pb.GlobResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Find: proto.Unmarshal: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	return pbresp, nil
}

func (z zipper) Render(metric, from, until string) (pb.FetchResponse, error) {

	u, _ := url.Parse(string(z) + "/render/")

	u.RawQuery = url.Values{
		"target": []string{metric},
		"format": []string{"protobuf"},
		"from":   []string{from},
		"until":  []string{until},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Render: http.Get: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Render: ioutil.ReadAll: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	var pbresp pb.FetchResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Render: proto.Unmarshal: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	return pbresp, nil
}

type limiter chan struct{}

func (l limiter) enter() { l <- struct{}{} }
func (l limiter) leave() { <-l }

var Limiter limiter

// for testing
var timeNow = time.Now

type graphitePoint struct {
	value float64
	t     int32
}

func (g graphitePoint) MarshalJSON() ([]byte, error) {
	// TODO(dgryski): fmt.Sprintf() is slow, use strconv.Append{Float,Int}
	if math.IsNaN(g.value) {
		return []byte(fmt.Sprintf("[null,%d]", g.t)), nil
	}
	return []byte(fmt.Sprintf("[%g,%d]", g.value, g.t)), nil
}

type jsonResponse struct {
	Target     string          `json:"target"`
	Datapoints []graphitePoint `json:"datapoints"`
}

func renderHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	targets := r.Form["target"]
	from := r.FormValue("from")
	until := r.FormValue("until")
	useCache := r.FormValue("noCache") == ""

	// make sure the cache key doesn't say noCache, because it will never hit
	r.Form.Del("noCache")

	cacheKey := r.Form.Encode()

	if response, ok := queryCache.get(cacheKey); useCache && ok {
		w.Header().Set("Content-Type", "application/json")
		w.Write(response)
		return
	}

	// normalize from and until values
	from = dateParamToEpoch(from, timeNow().Add(-24*time.Hour).Unix())
	until = dateParamToEpoch(until, timeNow().Unix())

	var results []*pb.FetchResponse

	for _, target := range targets {

		exp, e, err := parseExpr(target)
		if err != nil || e != "" {
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}

		metricMap := make(map[string][]*pb.FetchResponse)

		for _, metric := range exp.metrics() {

			var glob pb.GlobResponse
			var haveCacheData bool

			if response, ok := findCache.get(metric); useCache && ok {
				err := proto.Unmarshal(response, &glob)
				haveCacheData = err == nil
			}

			if !haveCacheData {
				var err error
				glob, err = Zipper.Find(metric)
				if err != nil {
					continue
				}
				b, err := proto.Marshal(&glob)
				if err == nil {
					findCache.set(metric, b)
				}
			}

			// For each metric returned in the Find response, query Render
			rch := make(chan *pb.FetchResponse, len(glob.GetMatches()))
			leaves := 0
			for _, m := range glob.GetMatches() {
				if !m.GetIsLeaf() {
					continue
				}
				leaves++
				Limiter.enter()
				go func(m *pb.GlobMatch) {
					var rptr *pb.FetchResponse
					r, err := Zipper.Render(m.GetPath(), from, until)
					if err == nil {
						rptr = &r
					}
					rch <- rptr
					Limiter.leave()
				}(m)
			}

			for i := 0; i < leaves; i++ {
				r := <-rch
				if r != nil {
					metricMap[metric] = append(metricMap[metric], r)
				}
			}
		}

		exprs := evalExpr(exp, metricMap)
		results = append(results, exprs...)
	}

	var jresults []jsonResponse

	for _, r := range results {
		if r == nil {
			log.Println("skipping nil result")
		}
		datapoints := make([]graphitePoint, 0, len(r.Values))
		t := *r.StartTime
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				v = math.NaN()
			}
			datapoints = append(datapoints, graphitePoint{value: v, t: t})
			t += *r.StepTime
		}
		jresults = append(jresults, jsonResponse{Target: r.GetName(), Datapoints: datapoints})
	}

	jout, err := json.Marshal(jresults)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	queryCache.set(cacheKey, jout)

	w.Header().Set("Content-Type", "application/json")
	w.Write(jout)
}

func main() {

	z := flag.String("z", "", "zipper")
	port := flag.Int("p", 8080, "port")
	l := flag.Int("l", 20, "concurrency limit")
	mc := flag.String("mc", "", "comma separated memcached server list")
	cpus := flag.Int("cpus", 0, "number of CPUs to use")

	flag.Parse()

	if *z == "" {
		log.Fatal("no zipper (-z) provided")
	}

	if p := os.Getenv("PORT"); p != "" {
		*port, _ = strconv.Atoi(p)
	}

	Limiter = make(chan struct{}, *l)

	if *z == "" {
		log.Fatal("no zipper provided")
	}

	if _, err := url.Parse(*z); err != nil {
		log.Fatal("unable to parze zipper:", err)
	}

	log.Println("using zipper", *z)

	if *mc != "" {
		servers := strings.Split(*mc, ",")
		queryCache = &memcachedCache{client: memcache.New(servers...)}
		findCache = &memcachedCache{client: memcache.New(servers...)}
	} else {
		queryCache = &expireCache{cache: make(map[string]cacheElement)}
		go queryCache.(*expireCache).cleaner()

		findCache = &expireCache{cache: make(map[string]cacheElement)}
		go findCache.(*expireCache).cleaner()
	}

	Zipper = zipper(*z)

	if *cpus != 0 {
		log.Println("using GOMAXPROCS", *cpus)
		runtime.GOMAXPROCS(*cpus)
	}

	http.HandleFunc("/render/", renderHandler)

	log.Println("listening on port", *port)
	log.Fatalln(http.ListenAndServe(":"+strconv.Itoa(*port), nil))

}
<|endoftext|>


<commit_before>package main

import (
	"crypto/subtle"
	"fmt"
	"html/template"
	"net/http"
)

var app *App
var templates *template.Template

func homeHandler(w http.ResponseWriter, r *http.Request) {
	domain := r.Host
	if site, err := app.SiteForDomain(domain); err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
	} else {
		if len(site.AuthUser) > 0 && len(site.AuthPass) > 0 {
			if u, p, ok := r.BasicAuth(); !ok || u != site.AuthUser || subtle.ConstantTimeCompare([]byte(p), []byte(site.AuthPass)) != 1 {
				w.Header().Set("WWW-Authenticate", `Basic realm="You need a username/password to access this site"`)
				w.WriteHeader(401)
				w.Write([]byte("Unauthorized\n"))
				return
			}
		}

		if imageUrls, err := site.GetAllImageUrls(); err != nil {
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
		} else {
			type HomeContext struct {
				MetaTitle            string
				SiteTitle            string
				AlbumTitle           string
				LoadAtStartImageUrls []string
				LazyLoadImageUrls    []string
			}

			loadAtStartImageUrls, lazyLoadImageUrls := imageUrls, imageUrls
			if len(imageUrls) > 10 {
				loadAtStartImageUrls = loadAtStartImageUrls[:10]
				lazyLoadImageUrls = lazyLoadImageUrls[10:]
			}
			ctx := &HomeContext{
				site.MetaTitle,
				site.SiteTitle,
				site.AlbumTitle,
				loadAtStartImageUrls,
				lazyLoadImageUrls,
			}
			templates.ExecuteTemplate(w, "home.html", ctx)
		}
	}
}

func main() {
	app = NewApp()
	templates = template.Must(template.ParseFiles("templates/home.html"))

	http.HandleFunc("/", homeHandler)
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))

	fmt.Printf("Starting server at port %s\n", app.port)
	if err := http.ListenAndServe(fmt.Sprintf(":%s", app.port), nil); err != nil {
		fmt.Printf("Unable to start server. Error: %s\n", err.Error())
	}
}
<commit_msg>Bug fix<commit_after>package main

import (
	"crypto/subtle"
	"fmt"
	"html/template"
	"net/http"
)

var app *App
var templates *template.Template

func homeHandler(w http.ResponseWriter, r *http.Request) {
	domain := r.Host
	if site, err := app.SiteForDomain(domain); err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
	} else {
		if len(site.AuthUser) > 0 && len(site.AuthPass) > 0 {
			if u, p, ok := r.BasicAuth(); !ok || u != site.AuthUser || subtle.ConstantTimeCompare([]byte(p), []byte(site.AuthPass)) != 1 {
				w.Header().Set("WWW-Authenticate", `Basic realm="You need a username/password to access this site"`)
				w.WriteHeader(401)
				w.Write([]byte("Unauthorized\n"))
				return
			}
		}

		if imageUrls, err := site.GetAllImageUrls(); err != nil {
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
		} else {
			type HomeContext struct {
				MetaTitle            string
				SiteTitle            string
				AlbumTitle           string
				LoadAtStartImageUrls []string
				LazyLoadImageUrls    []string
			}

			loadAtStartImageUrls, lazyLoadImageUrls := imageUrls, []string{}
			if len(imageUrls) > 10 {
				loadAtStartImageUrls = imageUrls[:10]
				lazyLoadImageUrls = imageUrls[10:]
			}
			ctx := &HomeContext{
				site.MetaTitle,
				site.SiteTitle,
				site.AlbumTitle,
				loadAtStartImageUrls,
				lazyLoadImageUrls,
			}
			templates.ExecuteTemplate(w, "home.html", ctx)
		}
	}
}

func main() {
	app = NewApp()
	templates = template.Must(template.ParseFiles("templates/home.html"))

	http.HandleFunc("/", homeHandler)
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))

	fmt.Printf("Starting server at port %s\n", app.port)
	if err := http.ListenAndServe(fmt.Sprintf(":%s", app.port), nil); err != nil {
		fmt.Printf("Unable to start server. Error: %s\n", err.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/codegangsta/cli"
	"github.com/gorilla/websocket"

	"github.com/scraperwiki/hookbot/listen"
	"github.com/scraperwiki/hookbot/router/github"
)

func main() {
	app := cli.NewApp()
	app.Name = "hookbot"
	app.Usage = "turn webhooks into websockets"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "key",
			Usage:  "secret known only for hootbot for URL access control",
			EnvVar: "HOOKBOT_KEY",
		},
		cli.StringFlag{
			Name:   "github-secret",
			Usage:  "secret known by github for signing messages",
			EnvVar: "HOOKBOT_GITHUB_SECRET",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:   "serve",
			Usage:  "start a hookbot instance, listening on http",
			Action: ActionServe,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "bind, b",
					Value: ":8080",
					Usage: "address to listen on",
				},
			},
		},
		{
			Name:    "make-tokens",
			Aliases: []string{"t"},
			Usage:   "given a list of URIs, generate tokens one per line",
			Action:  ActionMakeTokens,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "bare",
					Usage: "print only tokens (not as basic-auth URLs)",
				},
				cli.StringFlag{
					Name:   "url-base, U",
					Value:  "http://localhost:8080",
					Usage:  "base URL to generate for (not included in hmac)",
					EnvVar: "HOOKBOT_URL_BASE",
				},
			},
		},
		{
			Name:   "route-github",
			Usage:  "route github requests",
			Action: github.ActionRoute,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "monitor-url, u",
					Usage: "URL to monitor",
				},
				cli.StringFlag{
					Name:   "origin",
					Value:  "samehost",
					Usage:  "URL to use for the origin header ('samehost' is special)",
					EnvVar: "HOOKBOT_ORIGIN",
				},
				cli.StringSliceFlag{
					Name:   "header, H",
					Usage:  "headers to pass to the remote",
					Value:  &cli.StringSlice{},
					EnvVar: "HOOKBOT_HEADER",
				},
			},
		},
	}

	app.RunAndExitOnError()
}

var SubscribeURIRE = regexp.MustCompile("^(?:/unsafe)?/sub")

func ActionMakeTokens(c *cli.Context) {
	if !c.GlobalIsSet("key") {
		log.Fatalln("HOOKBOT_KEY not set")
	}

	key := c.GlobalString("key")

	if len(c.Args()) < 1 {
		cli.ShowSubcommandHelp(c)
		os.Exit(1)
	}

	baseStr := c.String("url-base")
	u, err := url.ParseRequestURI(baseStr)
	if err != nil {
		log.Fatal("Unable to parse url-base %q: %v", baseStr, err)
	}

	initialScheme := u.Scheme

	getScheme := func(target string) string {

		scheme := "http"

		secure := "" // if https or wss, "s", "" otherwise.
		switch initialScheme {
		case "https", "wss":
			secure = "s"
		}

		// If it's pub, use http(s), sub ws(s)
		if SubscribeURIRE.MatchString(target) {
			scheme = "ws"
		}
		return scheme + secure
	}

	for _, arg := range c.Args() {
		mac := Sha1HMAC(key, arg)
		if c.Bool("bare") {
			fmt.Println(mac)
		} else {
			u.Scheme = getScheme(arg)
			u.User = url.User(mac)
			u.Path = arg
			fmt.Println(u)
		}
	}
}

func ActionServe(c *cli.Context) {
	if !c.GlobalIsSet("key") {
		log.Fatalln("HOOKBOT_KEY not set")
	}

	key := c.GlobalString("key")

	hookbot := NewHookbot(key)

	http.Handle("/", hookbot)
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "OK")
	})

	log.Println("Listening on", c.String("bind"))
	err := http.ListenAndServe(c.String("bind"), nil)
	if err != nil {
		log.Fatal(err)
	}
}

type Message struct {
	Topic string
	Body  []byte
	Done  chan struct{} // signalled when messages have been strobed
	// (this is not the same as when they have been received)
}

type Listener struct {
	Topic string
	c     chan []byte
	ready chan struct{} // closed when c is subscribed
}

type Hookbot struct {
	key string

	wg       *sync.WaitGroup
	shutdown chan struct{}

	http.Handler

	message                  chan Message
	addListener, delListener chan Listener
}

func NewHookbot(key string) *Hookbot {
	h := &Hookbot{
		key: key,

		wg:       &sync.WaitGroup{},
		shutdown: make(chan struct{}),

		message:     make(chan Message, 1),
		addListener: make(chan Listener, 1),
		delListener: make(chan Listener, 1),
	}

	sub := WebsocketHandlerFunc(h.ServeSubscribe)
	pub := http.HandlerFunc(h.ServePublish)

	mux := http.NewServeMux()
	mux.Handle("/sub/", h.KeyChecker(sub))
	mux.Handle("/pub/", h.KeyChecker(pub))

	// Require the key *and* a declaration that unsafe messages are OK.
	mux.Handle("/unsafe/sub/", RequireUnsafeHeader(h.KeyChecker(sub)))

	// Unsafe can be published to from anywhere, no key required.
	// (so no KeyChecker)
	mux.Handle("/unsafe/pub/", http.HandlerFunc(h.ServePublish))

	h.Handler = mux

	h.wg.Add(1)
	go h.Loop()

	return h
}

var timeout = 1 * time.Second

func TimeoutSend(wg *sync.WaitGroup, c chan []byte, m []byte) {
	defer wg.Done()

	select {
	case c <- m:
	case <-time.After(timeout):
	}
}

// Shut down main loop and wait for all in-flight messages to send or timeout
func (h *Hookbot) Shutdown() {
	close(h.shutdown)
	h.wg.Wait()
}

// Returns "true" if fullTopic ends with `?recursive` and returns topic name
// without `?recursive` suffix.
func recursive(fullTopic string) (topic string, isRecursive bool) {
	if strings.HasSuffix(fullTopic, "?recursive") {
		return fullTopic[:len(fullTopic)-len("?recursive")], true
	}
	return fullTopic, false
}

// Manage fanout from h.message onto listeners
func (h *Hookbot) Loop() {
	defer h.wg.Done()

	// Map of topic to interested listeners
	listeners := map[string]map[Listener]struct{}{}

	// Return the set of interested listeners for a topic, considering
	// recursive watches.
	interested := func(topic string) map[Listener]struct{} {

		ls := map[Listener]struct{}{}

		// Non-recursive
		for l := range listeners[topic] {
			ls[l] = struct{}{}
		}

		// Recursive
		for fullCandidateTopic, candidateLs := range listeners {
			candidateTopic, isRec := recursive(fullCandidateTopic)
			if !isRec {
				continue
			}
			// Does the topic for signalling have a prefix our recursive
			// listeners are interested in?
			if !strings.HasPrefix(topic, candidateTopic) {
				continue
			}
			for l := range candidateLs {
				ls[l] = struct{}{}
			}
		}
		return ls
	}

	for {
		select {
		case m := <-h.message:

			// Strobe all interested listeners
			for listener := range interested(m.Topic) {
				h.wg.Add(1)
				go TimeoutSend(h.wg, listener.c, m.Body)
			}

			close(m.Done)

		case l := <-h.addListener:
			if _, ok := listeners[l.Topic]; !ok {
				listeners[l.Topic] = map[Listener]struct{}{}
			}
			listeners[l.Topic][l] = struct{}{}
			close(l.ready)

		case l := <-h.delListener:
			delete(listeners[l.Topic], l)
			if len(listeners[l.Topic]) == 0 {
				delete(listeners, l.Topic)
			}

		case <-h.shutdown:
			return
		}
	}
}

func (h *Hookbot) Add(topic string) Listener {
	ready := make(chan struct{})
	l := Listener{
		Topic: topic,
		// Use a channel depth of 1 so that tests don't require reading it
		// synchronously.
		c:     make(chan []byte, 1),
		ready: ready,
	}
	h.addListener <- l
	<-ready // wait until "c" in the subscribed map, for testing.
	return l
}

func (h *Hookbot) Del(l Listener) {
	h.delListener <- l
}

// The topic is everything after the "/pub/" or "/sub/"
// Do not capture the "/unsafe". See note in `Topic()`.
var TopicRE *regexp.Regexp = regexp.MustCompile("^(?:/unsafe)?/[^/]+/(.*)$")

func Topic(r *http.Request) string {
	m := TopicRE.FindStringSubmatch(r.URL.Path)
	if m == nil {
		return ""
	}
	topic := m[1]
	if IsUnsafeRequest(r) {
		// Note: `topic` cannot start `/unsafe/`, so it's
		// not possible to alias it.
		return "/unsafe/" + topic
	}
	return topic
}

func (h *Hookbot) ServePublish(w http.ResponseWriter, r *http.Request) {

	done := make(chan struct{})

	topic := Topic(r)

	var (
		body []byte
		err  error
	)

	if r.Header.Get("Content-Type") == "application/hookbot+any" {
		body, err = ioutil.ReadAll(r.Body)
	} else {
		body, err = json.Marshal(listen.Message{r})
	}

	if err != nil {
		log.Println("Error in ServePublish:", err)
		http.Error(w, "500 Internal Server Error", http.StatusInternalServerError)
		return
	}

	log.Printf("Publish %q", topic)

	h.message <- Message{Topic: topic, Body: body, Done: done}
	fmt.Fprintln(w, "OK")

	// TODO(pwaller): Loop over applicable routers here

	// Wait for the listeners to be strobed.
	// This is needed for testing purposes.
	// :-(
	<-done
}

func (h *Hookbot) ServeSubscribe(conn *websocket.Conn, r *http.Request) {

	topic := Topic(r)

	listener := h.Add(topic)
	defer h.Del(listener)

	closed := make(chan struct{})

	go func() {
		defer close(closed)
		for {
			if _, _, err := conn.NextReader(); err != nil {
				conn.Close()
				return
			}
		}
	}()

	var message []byte

	for {
		select {
		case message = <-listener.c:
		case <-closed:
			log.Printf("Client disconnected")
			return
		}

		conn.SetWriteDeadline(time.Now().Add(90 * time.Second))
		err := conn.WriteMessage(websocket.BinaryMessage, message)
		switch {
		case err == io.EOF:
			return // done
		case err != nil:
			log.Printf("Error in conn.WriteMessage: %v", err)
			return // unknown error
		}
	}
}
<commit_msg>Fix for unset environment variables<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/codegangsta/cli"
	"github.com/gorilla/websocket"

	"github.com/scraperwiki/hookbot/listen"
	"github.com/scraperwiki/hookbot/router/github"
)

func main() {
	app := cli.NewApp()
	app.Name = "hookbot"
	app.Usage = "turn webhooks into websockets"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "key",
			Usage:  "secret known only for hootbot for URL access control",
			Value:  "<unset>",
			EnvVar: "HOOKBOT_KEY",
		},
		cli.StringFlag{
			Name:   "github-secret",
			Usage:  "secret known by github for signing messages",
			Value:  "<unset>",
			EnvVar: "HOOKBOT_GITHUB_SECRET",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:   "serve",
			Usage:  "start a hookbot instance, listening on http",
			Action: ActionServe,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "bind, b",
					Value: ":8080",
					Usage: "address to listen on",
				},
			},
		},
		{
			Name:    "make-tokens",
			Aliases: []string{"t"},
			Usage:   "given a list of URIs, generate tokens one per line",
			Action:  ActionMakeTokens,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "bare",
					Usage: "print only tokens (not as basic-auth URLs)",
				},
				cli.StringFlag{
					Name:   "url-base, U",
					Value:  "http://localhost:8080",
					Usage:  "base URL to generate for (not included in hmac)",
					EnvVar: "HOOKBOT_URL_BASE",
				},
			},
		},
		{
			Name:   "route-github",
			Usage:  "route github requests",
			Action: github.ActionRoute,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "monitor-url, u",
					Usage: "URL to monitor",
				},
				cli.StringFlag{
					Name:   "origin",
					Value:  "samehost",
					Usage:  "URL to use for the origin header ('samehost' is special)",
					EnvVar: "HOOKBOT_ORIGIN",
				},
				cli.StringSliceFlag{
					Name:   "header, H",
					Usage:  "headers to pass to the remote",
					Value:  &cli.StringSlice{},
					EnvVar: "HOOKBOT_HEADER",
				},
			},
		},
	}

	app.RunAndExitOnError()
}

var SubscribeURIRE = regexp.MustCompile("^(?:/unsafe)?/sub")

func ActionMakeTokens(c *cli.Context) {
	key := c.GlobalString("key")
	if key == "<unset>" {
		log.Fatalln("HOOKBOT_KEY not set")
	}

	if len(c.Args()) < 1 {
		cli.ShowSubcommandHelp(c)
		os.Exit(1)
	}

	baseStr := c.String("url-base")
	u, err := url.ParseRequestURI(baseStr)
	if err != nil {
		log.Fatal("Unable to parse url-base %q: %v", baseStr, err)
	}

	initialScheme := u.Scheme

	getScheme := func(target string) string {

		scheme := "http"

		secure := "" // if https or wss, "s", "" otherwise.
		switch initialScheme {
		case "https", "wss":
			secure = "s"
		}

		// If it's pub, use http(s), sub ws(s)
		if SubscribeURIRE.MatchString(target) {
			scheme = "ws"
		}
		return scheme + secure
	}

	for _, arg := range c.Args() {
		mac := Sha1HMAC(key, arg)
		if c.Bool("bare") {
			fmt.Println(mac)
		} else {
			u.Scheme = getScheme(arg)
			u.User = url.User(mac)
			u.Path = arg
			fmt.Println(u)
		}
	}
}

func ActionServe(c *cli.Context) {
	key := c.GlobalString("key")
	if key == "<unset>" {
		log.Fatalln("HOOKBOT_KEY not set")
	}

	hookbot := NewHookbot(key)

	http.Handle("/", hookbot)
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "OK")
	})

	log.Println("Listening on", c.String("bind"))
	err := http.ListenAndServe(c.String("bind"), nil)
	if err != nil {
		log.Fatal(err)
	}
}

type Message struct {
	Topic string
	Body  []byte
	Done  chan struct{} // signalled when messages have been strobed
	// (this is not the same as when they have been received)
}

type Listener struct {
	Topic string
	c     chan []byte
	ready chan struct{} // closed when c is subscribed
}

type Hookbot struct {
	key string

	wg       *sync.WaitGroup
	shutdown chan struct{}

	http.Handler

	message                  chan Message
	addListener, delListener chan Listener
}

func NewHookbot(key string) *Hookbot {
	h := &Hookbot{
		key: key,

		wg:       &sync.WaitGroup{},
		shutdown: make(chan struct{}),

		message:     make(chan Message, 1),
		addListener: make(chan Listener, 1),
		delListener: make(chan Listener, 1),
	}

	sub := WebsocketHandlerFunc(h.ServeSubscribe)
	pub := http.HandlerFunc(h.ServePublish)

	mux := http.NewServeMux()
	mux.Handle("/sub/", h.KeyChecker(sub))
	mux.Handle("/pub/", h.KeyChecker(pub))

	// Require the key *and* a declaration that unsafe messages are OK.
	mux.Handle("/unsafe/sub/", RequireUnsafeHeader(h.KeyChecker(sub)))

	// Unsafe can be published to from anywhere, no key required.
	// (so no KeyChecker)
	mux.Handle("/unsafe/pub/", http.HandlerFunc(h.ServePublish))

	h.Handler = mux

	h.wg.Add(1)
	go h.Loop()

	return h
}

var timeout = 1 * time.Second

func TimeoutSend(wg *sync.WaitGroup, c chan []byte, m []byte) {
	defer wg.Done()

	select {
	case c <- m:
	case <-time.After(timeout):
	}
}

// Shut down main loop and wait for all in-flight messages to send or timeout
func (h *Hookbot) Shutdown() {
	close(h.shutdown)
	h.wg.Wait()
}

// Returns "true" if fullTopic ends with `?recursive` and returns topic name
// without `?recursive` suffix.
func recursive(fullTopic string) (topic string, isRecursive bool) {
	if strings.HasSuffix(fullTopic, "?recursive") {
		return fullTopic[:len(fullTopic)-len("?recursive")], true
	}
	return fullTopic, false
}

// Manage fanout from h.message onto listeners
func (h *Hookbot) Loop() {
	defer h.wg.Done()

	// Map of topic to interested listeners
	listeners := map[string]map[Listener]struct{}{}

	// Return the set of interested listeners for a topic, considering
	// recursive watches.
	interested := func(topic string) map[Listener]struct{} {

		ls := map[Listener]struct{}{}

		// Non-recursive
		for l := range listeners[topic] {
			ls[l] = struct{}{}
		}

		// Recursive
		for fullCandidateTopic, candidateLs := range listeners {
			candidateTopic, isRec := recursive(fullCandidateTopic)
			if !isRec {
				continue
			}
			// Does the topic for signalling have a prefix our recursive
			// listeners are interested in?
			if !strings.HasPrefix(topic, candidateTopic) {
				continue
			}
			for l := range candidateLs {
				ls[l] = struct{}{}
			}
		}
		return ls
	}

	for {
		select {
		case m := <-h.message:

			// Strobe all interested listeners
			for listener := range interested(m.Topic) {
				h.wg.Add(1)
				go TimeoutSend(h.wg, listener.c, m.Body)
			}

			close(m.Done)

		case l := <-h.addListener:
			if _, ok := listeners[l.Topic]; !ok {
				listeners[l.Topic] = map[Listener]struct{}{}
			}
			listeners[l.Topic][l] = struct{}{}
			close(l.ready)

		case l := <-h.delListener:
			delete(listeners[l.Topic], l)
			if len(listeners[l.Topic]) == 0 {
				delete(listeners, l.Topic)
			}

		case <-h.shutdown:
			return
		}
	}
}

func (h *Hookbot) Add(topic string) Listener {
	ready := make(chan struct{})
	l := Listener{
		Topic: topic,
		// Use a channel depth of 1 so that tests don't require reading it
		// synchronously.
		c:     make(chan []byte, 1),
		ready: ready,
	}
	h.addListener <- l
	<-ready // wait until "c" in the subscribed map, for testing.
	return l
}

func (h *Hookbot) Del(l Listener) {
	h.delListener <- l
}

// The topic is everything after the "/pub/" or "/sub/"
// Do not capture the "/unsafe". See note in `Topic()`.
var TopicRE *regexp.Regexp = regexp.MustCompile("^(?:/unsafe)?/[^/]+/(.*)$")

func Topic(r *http.Request) string {
	m := TopicRE.FindStringSubmatch(r.URL.Path)
	if m == nil {
		return ""
	}
	topic := m[1]
	if IsUnsafeRequest(r) {
		// Note: `topic` cannot start `/unsafe/`, so it's
		// not possible to alias it.
		return "/unsafe/" + topic
	}
	return topic
}

func (h *Hookbot) ServePublish(w http.ResponseWriter, r *http.Request) {

	done := make(chan struct{})

	topic := Topic(r)

	var (
		body []byte
		err  error
	)

	if r.Header.Get("Content-Type") == "application/hookbot+any" {
		body, err = ioutil.ReadAll(r.Body)
	} else {
		body, err = json.Marshal(listen.Message{r})
	}

	if err != nil {
		log.Println("Error in ServePublish:", err)
		http.Error(w, "500 Internal Server Error", http.StatusInternalServerError)
		return
	}

	log.Printf("Publish %q", topic)

	h.message <- Message{Topic: topic, Body: body, Done: done}
	fmt.Fprintln(w, "OK")

	// TODO(pwaller): Loop over applicable routers here

	// Wait for the listeners to be strobed.
	// This is needed for testing purposes.
	// :-(
	<-done
}

func (h *Hookbot) ServeSubscribe(conn *websocket.Conn, r *http.Request) {

	topic := Topic(r)

	listener := h.Add(topic)
	defer h.Del(listener)

	closed := make(chan struct{})

	go func() {
		defer close(closed)
		for {
			if _, _, err := conn.NextReader(); err != nil {
				conn.Close()
				return
			}
		}
	}()

	var message []byte

	for {
		select {
		case message = <-listener.c:
		case <-closed:
			log.Printf("Client disconnected")
			return
		}

		conn.SetWriteDeadline(time.Now().Add(90 * time.Second))
		err := conn.WriteMessage(websocket.BinaryMessage, message)
		switch {
		case err == io.EOF:
			return // done
		case err != nil:
			log.Printf("Error in conn.WriteMessage: %v", err)
			return // unknown error
		}
	}
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io/ioutil"
	"log"
  //"unicode/utf8"
  //"container/list"
  //"bytes"
	"net/http"
	//"encoding/json"
	//"net/url"
    "strings"
	// "database/sql"
	"os"
	"github.com/line/line-bot-sdk-go/linebot"
	// _ "github.com/go-sql-driver/mysql"
)

var bot *linebot.Client
var echo string
var op string
var bottun bool

type Data struct{
    resultType string `json:"resultType"`
    resultQuestion string `json:"resultQuestion"`
    resultContent []content `json:"resultContent"`
    requirementType string `json:"requirementType"`
}

type content struct{
    entity string `json:"entity"`
    Type string `json:"Type"`
}

var d Data

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)

    http.HandleFunc("/", sayhelloName) // set router
    err := http.ListenAndServe(":9090", nil) // set listen port
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }

    bottun = false
}

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()  // parse arguments, you have to call this by yourself
    fmt.Println(r.Form)  // print form information in server side
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["url_long"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, "Hello astaxie!") // send data to client side
}

// func mysql(){
// 	var db, err = sql.Open("mysql","wmlab:wmlab@tcp(140.115.54.82:3306)/wmlab?charset=utf8")
// 	if err != nil {
// 		fmt.Println(err)
//          // Just for example purpose. You should use proper error handling instead of panic
//     }
//     defer db.Close()

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

// 	rows, err := db.Query("select * from test")
// 	if err != nil {
// 		log.Println(err)
// 	}

// 	defer rows.Close()
// 	var col1 int
// 	for rows.Next() {
// 		err := rows.Scan(&col1)
// 		if err != nil {
// 			log.Fatal(err)
// 		}
// 		dbinfo=col1
// 	}
// }
func httpGet(q string , id string) {

    echo = "OK"
    bottun = false
    op = ""

    // q = strings.Replace( q , " " , "," , -1)

    resp, err := http.Get("http://140.115.54.93:54321/chatbot?q="+q+"&id="+id)
    if err != nil {
        // handle error
       panic(err.Error())
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        // handle error
       panic(err.Error())
    }

    echo = string(body)

    if echo == "正在為您轉接"{
        _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(q)).Do()
        if err != nil {
        // handle error
        echo = err.Error()
        }
    }

    // _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(echo)).Do()

    //------------for Luis
    // var r =  map[string]interface{}{}
    // var tempString string
    // tempString =string(body)

    // temp1 := strings.Split(tempString,"entity")
    // temp2 := strings.Split(tempString,"\"Type")
    // entity := list.New()
    // Type := list.New()
    // for i := 0; i < len(temp1); i++ {
    //   if i>=1{
    //     entity.PushBack( strings.Split(strings.Split(temp1[i],"\",")[0],":\"")[1] )
    //   }
    // }
    // for i := 0; i < len(temp2); i++ {
    //   if i>=1{
    //     Type.PushBack( strings.Split(strings.Split(temp2[i],"\"}")[0],":\"")[1] )
    //   }
    // }
    // json.Unmarshal(body, &r)

    // if r["resultType"].(string) == "none" {
    //   echo = "我不了解你在說什麼～@@"
    // } else if r["resultType"].(string) == "greeting" {
    //   echo = "你好！我是LUIS！我可以提供您數學的教材或是練習題喔！"
    // } else if r["resultType"].(string) == "appreciation" {
    //   echo = "歡迎您再次使用LUIS!我很樂意再次提供您服務！"
    // } else if r["resultType"].(string) == "connectionError" {
    //   echo = "對不起，我出了點問題，現在沒辦法回答你問題@@"
    // } else if r["resultType"].(string) == "unknown" {
    //   echo = "不好意思，我不知道你問的定理是什麼QQ"
    // } else if r["resultType"].(string) == "question" {
    //   if r["requirementType"].(string) == "none" {
    //     bottun = true
    //     for e:= entity.Front();e!=nil;e = e.Next(){

    //      op += e.Value.(string)
    //     }
    //   }
    // }

    //-----------------for luis

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

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

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:

        if op!= ""{
          echo ="OK"
          bottun = false

        } else if event.Source.UserID == ""{
            _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(message.Text)).Do()
            if err != nil {
            // handle error
            //    ..
            echo = err.Error()
            }

        } else {
        	httpGet(message.Text,event.Source.UserID)
        }
				// mysql()
				//message.ID+":"+message.Text
        if bottun {
           //_, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(echo)).Do()
            var ff string
            var gg string
            ff = "我要"+op+"的練習題"
            gg = "我要"+op+"的教材"
            leftBtn := linebot.NewMessageTemplateAction("練習題", ff)
            rightBtn := linebot.NewMessageTemplateAction("教材", gg)

            template := linebot.NewConfirmTemplate("請問是需要練習題還是教材?", leftBtn, rightBtn)

            templatemessgage := linebot.NewTemplateMessage("Sorry :(, please update your app.", template)
            _, err = bot.ReplyMessage(event.ReplyToken, templatemessgage).Do()
           //op=""

        } else {
           _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           // _, err = bot.PushMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           op=""
        }

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

package main

import (
	"fmt"
	"io/ioutil"
	"log"
  //"unicode/utf8"
  //"container/list"
  //"bytes"
	"net/http"
	//"encoding/json"
	//"net/url"
    "strings"
	// "database/sql"
	"os"
	"github.com/line/line-bot-sdk-go/linebot"
	// _ "github.com/go-sql-driver/mysql"
)

var bot *linebot.Client
var echo string
var op string
var bottun bool

type Data struct{
    resultType string `json:"resultType"`
    resultQuestion string `json:"resultQuestion"`
    resultContent []content `json:"resultContent"`
    requirementType string `json:"requirementType"`
}

type content struct{
    entity string `json:"entity"`
    Type string `json:"Type"`
}

var d Data

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)

    http.HandleFunc("/", sayhelloName) // set router
    addr := fmt.Sprintf(":%s", 9090)
    err := http.ListenAndServe(addr, nil) // set listen port
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }

    bottun = false
}

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()  // parse arguments, you have to call this by yourself
    fmt.Println(r.Form)  // print form information in server side
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["url_long"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, "Hello astaxie!") // send data to client side
}

// func mysql(){
// 	var db, err = sql.Open("mysql","wmlab:wmlab@tcp(140.115.54.82:3306)/wmlab?charset=utf8")
// 	if err != nil {
// 		fmt.Println(err)
//          // Just for example purpose. You should use proper error handling instead of panic
//     }
//     defer db.Close()

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

// 	rows, err := db.Query("select * from test")
// 	if err != nil {
// 		log.Println(err)
// 	}

// 	defer rows.Close()
// 	var col1 int
// 	for rows.Next() {
// 		err := rows.Scan(&col1)
// 		if err != nil {
// 			log.Fatal(err)
// 		}
// 		dbinfo=col1
// 	}
// }
func httpGet(q string , id string) {

    echo = "OK"
    bottun = false
    op = ""

    // q = strings.Replace( q , " " , "," , -1)

    resp, err := http.Get("http://140.115.54.93:54321/chatbot?q="+q+"&id="+id)
    if err != nil {
        // handle error
       panic(err.Error())
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        // handle error
       panic(err.Error())
    }

    echo = string(body)

    if echo == "正在為您轉接"{
        _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(q)).Do()
        if err != nil {
        // handle error
        echo = err.Error()
        }
    }

    // _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(echo)).Do()

    //------------for Luis
    // var r =  map[string]interface{}{}
    // var tempString string
    // tempString =string(body)

    // temp1 := strings.Split(tempString,"entity")
    // temp2 := strings.Split(tempString,"\"Type")
    // entity := list.New()
    // Type := list.New()
    // for i := 0; i < len(temp1); i++ {
    //   if i>=1{
    //     entity.PushBack( strings.Split(strings.Split(temp1[i],"\",")[0],":\"")[1] )
    //   }
    // }
    // for i := 0; i < len(temp2); i++ {
    //   if i>=1{
    //     Type.PushBack( strings.Split(strings.Split(temp2[i],"\"}")[0],":\"")[1] )
    //   }
    // }
    // json.Unmarshal(body, &r)

    // if r["resultType"].(string) == "none" {
    //   echo = "我不了解你在說什麼～@@"
    // } else if r["resultType"].(string) == "greeting" {
    //   echo = "你好！我是LUIS！我可以提供您數學的教材或是練習題喔！"
    // } else if r["resultType"].(string) == "appreciation" {
    //   echo = "歡迎您再次使用LUIS!我很樂意再次提供您服務！"
    // } else if r["resultType"].(string) == "connectionError" {
    //   echo = "對不起，我出了點問題，現在沒辦法回答你問題@@"
    // } else if r["resultType"].(string) == "unknown" {
    //   echo = "不好意思，我不知道你問的定理是什麼QQ"
    // } else if r["resultType"].(string) == "question" {
    //   if r["requirementType"].(string) == "none" {
    //     bottun = true
    //     for e:= entity.Front();e!=nil;e = e.Next(){

    //      op += e.Value.(string)
    //     }
    //   }
    // }

    //-----------------for luis

}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

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

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:

        if op!= ""{
          echo ="OK"
          bottun = false

        } else if event.Source.UserID == ""{
            _, err = bot.PushMessage("Uf6263c4b814700c680228b8b64a27dd6", linebot.NewTextMessage(message.Text)).Do()
            if err != nil {
            // handle error
            //    ..
            echo = err.Error()
            }

        } else {
        	httpGet(message.Text,event.Source.UserID)
        }
				// mysql()
				//message.ID+":"+message.Text
        if bottun {
           //_, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(echo)).Do()
            var ff string
            var gg string
            ff = "我要"+op+"的練習題"
            gg = "我要"+op+"的教材"
            leftBtn := linebot.NewMessageTemplateAction("練習題", ff)
            rightBtn := linebot.NewMessageTemplateAction("教材", gg)

            template := linebot.NewConfirmTemplate("請問是需要練習題還是教材?", leftBtn, rightBtn)

            templatemessgage := linebot.NewTemplateMessage("Sorry :(, please update your app.", template)
            _, err = bot.ReplyMessage(event.ReplyToken, templatemessgage).Do()
           //op=""

        } else {
           _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           // _, err = bot.PushMessage(event.ReplyToken, linebot.NewTextMessage( echo )).Do()
           op=""
        }

			}
		}
	}
}
<|endoftext|>


<commit_before>// transfer2go - Go implementation of loosely coupled, distributed agents for data transfer
//
// Copyright (c) 2017 - Valentin Kuznetsov <vkuznet@gmail.com>
//
package main

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

	"github.com/vkuznet/transfer2go/client"
	"github.com/vkuznet/transfer2go/server"
	"github.com/vkuznet/transfer2go/utils"
)

func main() {

	// server options
	var agent string
	flag.StringVar(&agent, "agent", "", "Remote agent (registration) end-point")
	var configFile string
	flag.StringVar(&configFile, "config", "", "Agent configuration file")
	var verbose int
	flag.IntVar(&verbose, "verbose", 0, "Verbosity level")

	// client options
	var src string
	flag.StringVar(&src, "src", "", "Source end-point, either local file or AgentName:LFN")
	var dst string
	flag.StringVar(&dst, "dst", "", "Destination end-point, either AgentName or AgentName:LFN")
	var register string
	flag.StringVar(&register, "register", "", "File with meta-data of records in JSON data format to register at remote agent")

	var auth bool
	flag.Bool(&auth, "auth", true, "To disable the auth layer")

	flag.Parse()

	if auth {
		utils.CheckX509()
	}

	utils.VERBOSE = verbose
	if configFile != "" {
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Println("Unable to read", configFile, err)
			os.Exit(1)
		}
		var config server.Config
		err = json.Unmarshal(data, &config)
		if err != nil {
			log.Println("Unable to parse", configFile, err)
			os.Exit(1)
		}
		if config.Catalog == "" {
			pwd, err := os.Getwd()
			if err != nil {
				log.Println("Unable to get current directory", err)
				os.Exit(1)
			}
			config.Catalog = pwd // use current directory as catalog
		}
		if config.Workers == 0 {
			config.Workers = 10 // default value
		}
		if config.QueueSize == 0 {
			config.QueueSize = 100 // default value
		}
		if config.Protocol == "" {
			config.Protocol = "http" // default value
		}
		if config.Port == 0 {
			config.Port = 8989
		}
		if agent != "" {
			config.Register = agent
		}
		if config.Register == "" {
			log.Println("WARNING this agent is not registered with remote ones, either provide register in your config or invoke register API call")
		}

		config.Auth = auth

		server.Server(config)
	} else {
		var err error
		if register != "" {
			err = client.Register(agent, register)
		} else if src == "" { // no transfer request
			client.Agent(agent)
		} else {
			err = client.Transfer(agent, src, dst)
		}
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}
	}
}

// helper function to construct site name
func makeSiteName() string {
	host, err := os.Hostname()
	if err != nil {
		panic(fmt.Sprintf("Unable to get hostname, error=%v", err))
	}
	return fmt.Sprintf("T4_%s_%v", host, os.Getuid())
}
<commit_msg>Use oolVar<commit_after>// transfer2go - Go implementation of loosely coupled, distributed agents for data transfer
//
// Copyright (c) 2017 - Valentin Kuznetsov <vkuznet@gmail.com>
//
package main

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

	"github.com/vkuznet/transfer2go/client"
	"github.com/vkuznet/transfer2go/server"
	"github.com/vkuznet/transfer2go/utils"
)

func main() {

	// server options
	var agent string
	flag.StringVar(&agent, "agent", "", "Remote agent (registration) end-point")
	var configFile string
	flag.StringVar(&configFile, "config", "", "Agent configuration file")
	var verbose int
	flag.IntVar(&verbose, "verbose", 0, "Verbosity level")

	// client options
	var src string
	flag.StringVar(&src, "src", "", "Source end-point, either local file or AgentName:LFN")
	var dst string
	flag.StringVar(&dst, "dst", "", "Destination end-point, either AgentName or AgentName:LFN")
	var register string
	flag.StringVar(&register, "register", "", "File with meta-data of records in JSON data format to register at remote agent")

	var auth bool
	flag.BoolVar(&auth, "auth", true, "To disable the auth layer")

	flag.Parse()

	if auth {
		utils.CheckX509()
	}

	utils.VERBOSE = verbose
	if configFile != "" {
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Println("Unable to read", configFile, err)
			os.Exit(1)
		}
		var config server.Config
		err = json.Unmarshal(data, &config)
		if err != nil {
			log.Println("Unable to parse", configFile, err)
			os.Exit(1)
		}
		if config.Catalog == "" {
			pwd, err := os.Getwd()
			if err != nil {
				log.Println("Unable to get current directory", err)
				os.Exit(1)
			}
			config.Catalog = pwd // use current directory as catalog
		}
		if config.Workers == 0 {
			config.Workers = 10 // default value
		}
		if config.QueueSize == 0 {
			config.QueueSize = 100 // default value
		}
		if config.Protocol == "" {
			config.Protocol = "http" // default value
		}
		if config.Port == 0 {
			config.Port = 8989
		}
		if agent != "" {
			config.Register = agent
		}
		if config.Register == "" {
			log.Println("WARNING this agent is not registered with remote ones, either provide register in your config or invoke register API call")
		}

		config.Auth = auth

		server.Server(config)
	} else {
		var err error
		if register != "" {
			err = client.Register(agent, register)
		} else if src == "" { // no transfer request
			client.Agent(agent)
		} else {
			err = client.Transfer(agent, src, dst)
		}
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}
	}
}

// helper function to construct site name
func makeSiteName() string {
	host, err := os.Hostname()
	if err != nil {
		panic(fmt.Sprintf("Unable to get hostname, error=%v", err))
	}
	return fmt.Sprintf("T4_%s_%v", host, os.Getuid())
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"time"
)

const PROGVERSION string = "0.3.0"

type Config struct {
	Main struct {
		Address  string
		Port     int
		Sitename string
	}
}

var cfg Config

func init() {
	rand.Seed(time.Now().UnixNano())
	if !fexists("versions") {
		info("Creating data directory.")
		os.MkdirAll("versions", 0700)
	}
	if !fexists("updates") {
		info("Creating update directory.")
		os.MkdirAll("updates", 0700)
	}
}

func main() {
	var runupdates *bool = flag.Bool("u", false, "Run updates instead of launching web server.")
	var address *string = flag.String("a", "0.0.0.0", "Address to bind to.")
	var port *int = flag.Int("p", 8000, "Port to bind to.")
	var display *bool = flag.Bool("d", false, "Display versions and URLs available, then exit.")
	var version *string = flag.String("v", "", "Display a specific version. If not specified you get everything.")
	flag.Parse()

	if *runupdates {
		updateVersions()
		return
	}

	if *display {
		if *version == "" {
			displayVersions()
		} else {
			displayVersion(*version)
		}
		return
	}

	cfg.Main.Address = *address
	cfg.Main.Port = *port
	cfg.Main.Sitename = "Unity download links"
	initWeb()
	endWeb()
}

var baseurl1 = "http://download.unity3d.com/download_unity/"

//	baseurl2 := "http://beta.unity3d.com/download/"
//	url2 := "http://beta.unity3d.com/download/b6c1a63227dc/unity-5.3.2p3-osx.ini"
func updateVersions() {
	p("UnityLinks %s", PROGVERSION)
	files, err := ioutil.ReadDir("./updates")
	if err != nil {
		p("Error: %s.", err.Error())
		return
	}
	count := 0
	max := 0
	for _, fi := range files {
		if !fi.IsDir() {
			max++
			s, _ := ioutil.ReadFile("updates/" + fi.Name())
			if s != nil {
				hash := strings.Replace(string(s), "\n", "", -1)
				getMacIni(hash, fi.Name())
				getWinIni(hash, fi.Name())
				count++
			}
		}
	}
	info("Updated %d versions out of %d.", count, max)
}

func getVar(line string) string {
	return strings.TrimSpace(line[strings.IndexByte(line, '=')+1:])
}

func getMacIni(hash string, filename string) {
	url := baseurl1 + hash + "/unity-" + filename + "-osx.ini"

	info("Downloading %s", url)
	response, err := http.Get(url)
	if err != nil {
		p("Error downloading: %s", err.Error())
		return
	}
	defer response.Body.Close()
	bs, err := ioutil.ReadAll(response.Body)
	if err != nil {
		p("Error fetching OS X version: %s\n", err.Error())
		return
	}
	contents := string(bs)
	sections := strings.Split(contents, "[")
	data := ""
	for _, s := range sections {
		if len(s) > 0 {
			lines := strings.Split(s, "\n")
			data += getVar(lines[1]) + "\n"
			data += getVar(lines[2]) + "\n"
			data += baseurl1 + hash + "/" + getVar(lines[3]) + "\n"
			data += getVar(lines[4]) + "\n"
		}
	}
	p("Saving %s (OS X)\n", filename)
	saveVersion(filename, data)
}

//TODO: gcfg can't read the -win.ini properly. Make custom hack.
func getWinIni(hash string, filename string) {
	url := baseurl1 + hash + "/unity-" + filename + "-win.ini"

	info("Downloading %s", url)
	response, err := http.Get(url)
	if err != nil {
		p("Error downloading: %s", err.Error())
		return
	}
	defer response.Body.Close()
	bs, err := ioutil.ReadAll(response.Body)
	if err != nil {
		p("Error fetching Windows version: %s\n", err.Error())
		return
	}
	contents := string(bs)
	sections := strings.Split(contents, "[")
	data := ""
	for _, s := range sections {
		if len(s) > 0 {
			lines := strings.Split(s, "\n")
			data += getVar(lines[1]) + "\n"
			data += getVar(lines[2]) + "\n"
			l3 := baseurl1 + hash + "/" + getVar(lines[3])
			l4 := baseurl1 + hash + "/" + getVar(lines[4])
			data += l3 + "\n" + l4 + "\n"
		}
	}
	p("Saving %s (Windows)\n", filename)
	saveVersion(filename+".win", data)
}

func saveVersion(version string, data string) {
	file, err := os.OpenFile("versions/"+version, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		p("Error: %s.", err.Error())
		return
	}

	defer file.Close()
	file.WriteString(data)
	os.Remove("updates/" + version)
}

func displayVersions() {
	files, err := ioutil.ReadDir("versions")
	if err != nil {
		p("Error: %s.", err.Error())
		return
	}
	for _, fi := range files {
		if !fi.IsDir() {
			displayVersion(fi.Name())
		}
	}
}

func displayVersion(version string) {
	name := "versions/" + version
	s, _ := ioutil.ReadFile(name)
	p("%s\n", s)
}
<commit_msg>Fixed logic for retrying with different download sites, as 404 is not actually an error.<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"time"
)

const PROGVERSION string = "0.3.0"

type Config struct {
	Main struct {
		Address  string
		Port     int
		Sitename string
	}
}

var cfg Config

func init() {
	rand.Seed(time.Now().UnixNano())
	if !fexists("versions") {
		info("Creating data directory.")
		os.MkdirAll("versions", 0700)
	}
	if !fexists("updates") {
		info("Creating update directory.")
		os.MkdirAll("updates", 0700)
	}
}

func main() {
	var runupdates *bool = flag.Bool("u", false, "Run updates instead of launching web server.")
	var address *string = flag.String("a", "0.0.0.0", "Address to bind to.")
	var port *int = flag.Int("p", 8000, "Port to bind to.")
	var display *bool = flag.Bool("d", false, "Display versions and URLs available, then exit.")
	var version *string = flag.String("v", "", "Display a specific version. If not specified you get everything.")
	flag.Parse()

	if *runupdates {
		updateVersions()
		return
	}

	if *display {
		if *version == "" {
			displayVersions()
		} else {
			displayVersion(*version)
		}
		return
	}

	cfg.Main.Address = *address
	cfg.Main.Port = *port
	cfg.Main.Sitename = "Unity download links"
	initWeb()
	endWeb()
}

var baseurl1 = "http://download.unity3d.com/download_unity/"
var baseurl2 = "http://beta.unity3d.com/download/"

func updateVersions() {
	p("UnityLinks %s", PROGVERSION)
	files, err := ioutil.ReadDir("./updates")
	if err != nil {
		p("Error: %s.", err.Error())
		return
	}
	count := 0
	max := 0
	for _, fi := range files {
		if !fi.IsDir() {
			max++
			s, _ := ioutil.ReadFile("updates/" + fi.Name())
			if s != nil {
				hash := strings.Replace(string(s), "\n", "", -1)
				getMacIni(hash, fi.Name())
				getWinIni(hash, fi.Name())
				count++
			}
		}
	}
	info("Updated %d versions out of %d.", count, max)
}

func getVar(line string) string {
	return strings.TrimSpace(line[strings.IndexByte(line, '=')+1:])
}

func getMacIni(hash string, filename string) {
	url := baseurl1 + hash + "/unity-" + filename + "-osx.ini"
	url2 := baseurl2 + hash + "/unity-" + filename + "-osx.ini"

	info("Downloading %s", url)
	response, _ := http.Get(url)
	p("Status: %d\n", response.StatusCode)
	if response.StatusCode == 404 {
		p("Trying again with %s\n", url2)
		response, _ = http.Get(url2)
		if response.StatusCode == 404 {
			p("Error downloading %s\n", url2)
			return
		}
	}
	defer response.Body.Close()
	bs, err := ioutil.ReadAll(response.Body)
	if err != nil {
		p("Error fetching OS X version: %s\n", err.Error())
		return
	}
	contents := string(bs)
	sections := strings.Split(contents, "[")
	data := ""
	for _, s := range sections {
		if len(s) > 0 {
			lines := strings.Split(s, "\n")
			data += getVar(lines[1]) + "\n"
			data += getVar(lines[2]) + "\n"
			data += baseurl1 + hash + "/" + getVar(lines[3]) + "\n"
			data += getVar(lines[4]) + "\n"
		}
	}
	p("Saving %s (OS X)\n", filename)
	saveVersion(filename, data)
}

//TODO: gcfg can't read the -win.ini properly. Make custom hack.
func getWinIni(hash string, filename string) {
	url := baseurl1 + hash + "/unity-" + filename + "-win.ini"
	url2 := baseurl2 + hash + "/unity-" + filename + "-win.ini"

	info("Downloading %s", url)
	response, _ := http.Get(url)
	if response.StatusCode == 404 {
		p("Trying again with %s\n", url2)
		response, _ = http.Get(url2)
		if response.StatusCode == 404 {
			p("Error downloading %s", url2)
			return
		}
	}
	defer response.Body.Close()
	bs, err := ioutil.ReadAll(response.Body)
	if err != nil {
		p("Error fetching Windows version: %s\n", err.Error())
		return
	}
	contents := string(bs)
	sections := strings.Split(contents, "[")
	data := ""
	for _, s := range sections {
		if len(s) > 0 {
			lines := strings.Split(s, "\n")
			data += getVar(lines[1]) + "\n"
			data += getVar(lines[2]) + "\n"
			l3 := baseurl1 + hash + "/" + getVar(lines[3])
			l4 := baseurl1 + hash + "/" + getVar(lines[4])
			data += l3 + "\n" + l4 + "\n"
		}
	}
	p("Saving %s (Windows)\n", filename)
	saveVersion(filename+".win", data)
}

func saveVersion(version string, data string) {
	file, err := os.OpenFile("versions/"+version, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		p("Error: %s.", err.Error())
		return
	}

	defer file.Close()
	file.WriteString(data)
	os.Remove("updates/" + version)
}

func displayVersions() {
	files, err := ioutil.ReadDir("versions")
	if err != nil {
		p("Error: %s.", err.Error())
		return
	}
	for _, fi := range files {
		if !fi.IsDir() {
			displayVersion(fi.Name())
		}
	}
}

func displayVersion(version string) {
	name := "versions/" + version
	s, _ := ioutil.ReadFile(name)
	p("%s\n", s)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"net/http"

	"github.com/Tinker-Ware/gh-service/infrastructure"
	"github.com/Tinker-Ware/gh-service/interfaces"
	"github.com/Tinker-Ware/gh-service/usecases"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
)

const defaultPath = "/etc/gh-service.conf"

// Define configuration flags
var confFilePath = flag.String("conf", defaultPath, "Custom path for configuration file")

func main() {

	flag.Parse()

	config, err := infrastructure.GetConfiguration(*confFilePath)
	if err != nil {
		fmt.Println(err.Error())
		panic("Cannot parse configuration")
	}

	ghrepo, err := interfaces.NewGithubRepository(config.ClientID, config.ClientSecret, config.Scopes)
	if err != nil {
		panic(err.Error())
	}

	ghinteractor := usecases.GHInteractor{
		GithubRepository: ghrepo,
	}

	store := sessions.NewCookieStore([]byte("something-very-secret"))

	handler := interfaces.WebServiceHandler{
		GHInteractor: ghinteractor,
		Sessions:     store,
	}

	r := mux.NewRouter()

	subrouter := r.PathPrefix("/api/v1/repository/github").Subrouter()
	subrouter.Handle("/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.ShowRepos), interfaces.Notify(), interfaces.GetToken(ghrepo, config.Host, config.Salt))).Methods("GET")
	subrouter.Handle("/{username}/{repo}", interfaces.Adapt(http.HandlerFunc(handler.ShowRepo), interfaces.Notify(), interfaces.GetToken(ghrepo, config.Host, config.Salt))).Methods("GET")
	// subrouter.Handle("/user/{username}", interfaces.Adapt(http.HandlerFunc(handler.ShowUser), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys/{id}", interfaces.Adapt(http.HandlerFunc(handler.ShowKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/{repo}/addfile", interfaces.Adapt(http.HandlerFunc(handler.AddFileToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/{repo}/addfiles", interfaces.Adapt(http.HandlerFunc(handler.AddMultipleFilesToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.HandleFunc("/user_info", handler.GetCurrentUser).Methods("GET")

	n := negroni.Classic()
	n.UseHandler(r)

	port := bytes.Buffer{}

	port.WriteString(":")
	port.WriteString(config.Port)

	n.Run(port.String())
}
<commit_msg>Add Callback to router<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"net/http"

	"github.com/Tinker-Ware/gh-service/infrastructure"
	"github.com/Tinker-Ware/gh-service/interfaces"
	"github.com/Tinker-Ware/gh-service/usecases"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
)

const defaultPath = "/etc/gh-service.conf"

// Define configuration flags
var confFilePath = flag.String("conf", defaultPath, "Custom path for configuration file")

func main() {

	flag.Parse()

	config, err := infrastructure.GetConfiguration(*confFilePath)
	if err != nil {
		fmt.Println(err.Error())
		panic("Cannot parse configuration")
	}

	ghrepo, err := interfaces.NewGithubRepository(config.ClientID, config.ClientSecret, config.Scopes)
	if err != nil {
		panic(err.Error())
	}

	ghinteractor := usecases.GHInteractor{
		GithubRepository: ghrepo,
	}

	handler := interfaces.WebServiceHandler{
		GHInteractor: ghinteractor,
		APIHost:      config.APIHost,
	}

	r := mux.NewRouter()

	subrouter := r.PathPrefix("/api/v1/repository/github").Subrouter()
	subrouter.Handle("/oauth", interfaces.Adapt(http.HandlerFunc(handler.Callback), interfaces.Notify())).Methods("POST")
	subrouter.Handle("/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.ShowRepos), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))).Methods("GET")
	subrouter.Handle("/{username}/{repo}", interfaces.Adapt(http.HandlerFunc(handler.ShowRepo), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))).Methods("GET")
	// subrouter.Handle("/user/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys/{id}", interfaces.Adapt(http.HandlerFunc(handler.ShowKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/{repo}/addfile", interfaces.Adapt(http.HandlerFunc(handler.AddFileToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/{repo}/addfiles", interfaces.Adapt(http.HandlerFunc(handler.AddMultipleFilesToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.HandleFunc("/user_info", handler.GetCurrentUser).Methods("GET")

	n := negroni.Classic()
	n.UseHandler(r)

	port := bytes.Buffer{}

	port.WriteString(":")
	port.WriteString(config.Port)

	n.Run(port.String())
}
<|endoftext|>