<commit_before>package main

import (
	"context"
	"fmt"
	"github.com/christophwitzko/github-release-download/release"
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
	"os"
	"time"
)

var Client *release.GithubClient

func init() {
	Client = release.NewClient(os.Getenv("GITHUB_TOKEN"))
}

func FindDownload(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	log.Printf("%s - %s %s", r.RemoteAddr, r.Method, r.URL.EscapedPath())
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	url, err := Client.GetLatestDownloadUrl(ctx, ps[0].Value, ps[1].Value, ps[2].Value, ps[3].Value)
	if err != nil || url == "" {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	http.Redirect(w, r, url, 302)
}

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprintln(w, "https://get-release.xyz/:owner/:repo/:os/:arch")
}

func main() {
	router := httprouter.New()
	router.GET("/", Index)
	router.GET("/:owner/:repo/:os/:arch", FindDownload)

	log.Println("starting server on port 5000...")
	log.Fatal(http.ListenAndServe(":5000", router))
}
<commit_msg>feat: add constraint route<commit_after>package main

import (
	"context"
	"fmt"
	"github.com/christophwitzko/github-release-download/release"
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
	"os"
	"time"
)

var Client *release.GithubClient

func init() {
	Client = release.NewClient(os.Getenv("GITHUB_TOKEN"))
}

func logger(router http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s - %s %s", r.RemoteAddr, r.Method, r.URL.EscapedPath())
		router.ServeHTTP(w, r)
	})
}

func doRedirect(w http.ResponseWriter, r *http.Request, url string, err error) {
	if err != nil {
		log.Println(err)
		http.Error(w, "server error", http.StatusInternalServerError)
		return
	}
	if url == "" {
		http.NotFound(w, r)
		return
	}
	http.Redirect(w, r, url, 302)
}

func GetLatestDownload(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	url, err := Client.GetLatestDownloadUrl(ctx, ps[0].Value, ps[1].Value, ps[2].Value, ps[3].Value)
	doRedirect(w, r, url, err)
}

func GetMatchingDownload(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	url, err := Client.GetMatchingDownloadUrl(ctx, ps[0].Value, ps[1].Value, ps[2].Value, ps[3].Value, ps[4].Value)
	doRedirect(w, r, url, err)
}

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprintln(w, "https://get-release.xyz/:owner/:repo/:os/:arch{/:constraint}")
}

func main() {
	router := httprouter.New()
	router.GET("/", Index)
	router.GET("/:owner/:repo/:os/:arch", GetLatestDownload)
	router.GET("/:owner/:repo/:os/:arch/:constraint", GetMatchingDownload)
	log.Println("starting server on port 5000...")
	log.Fatal(http.ListenAndServe(":5000", logger(router)))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	. "github.com/whereswaldon/dijkstra/alg"
	"io"
	"os"
	"strconv"
	"strings"
)

// exit wraps an exit code with a type
type exit struct {
	Code int
}

// handleExit recovers from panics and checks whether the
// panic was caused by an exit request. If it was, it exits
// with that status code. Otherwise, it panics again.
func handleExit() {
	if r := recover(); r != nil {
		if e, ok := r.(exit); !ok {
			panic(r)
		} else {
			os.Exit(e.Code)
		}
	}
}

// setupGraph parses the file contents and creates a graph
// representing the file
func setupGraph(filename string) *Graph {
	fmt.Println("Opening", filename)
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("Unable to open file! ", err)
		panic(exit{1})
	}
	defer file.Close()
	buffReader := bufio.NewReader(file)
	nodes, err := buffReader.ReadString('\n')
	if err != nil {
		fmt.Println("Unable to read line! ", err)
		panic(exit{1})
	}
	nodes = strings.TrimSpace(nodes)
	order, err := strconv.Atoi(nodes)
	if err != nil {
		fmt.Println("Unable to convert nodes to integer")
		panic(exit{1})
	}
	graph := NewGraph(order)
	fmt.Println("There are", nodes, "nodes in the graph!")
	var u, v, weight int
	var line string
	for err == nil || err != io.EOF {
		line, err = buffReader.ReadString('\n')
		fmt.Sscanf(line, "%d %d %d\n", &u, &v, &weight)
		graph.InsertEdge(u, v, weight)
	}
	return graph
}

func main() {
	defer handleExit()
	var root int = 0
	var err error
	if len(os.Args) < 2 {
		fmt.Println("Please supply a filename as an argument")
		panic(exit{1})
	} else if len(os.Args) < 3 {
		fmt.Println("No root node specified, defaulting to zero")
	} else {
		root, err = strconv.Atoi(os.Args[2])
		if err != nil {
			fmt.Println("Unable to convert second argument to number: ", err)
			panic(exit{1})
		}
	}

	graph := setupGraph(os.Args[1])
	table := graph.FindShortestPathTree(root)

	fmt.Println(table)
	fmt.Println("Max distance: ", table.MaxDistance, " from ", table.Root, " to ", table.FurthestNode)
	s, e, d := graph.FindDiameter()
	fmt.Println("diameter: ", d, " start: ", s, " end: ", e)
}
<commit_msg>Rename package<commit_after>package main

import (
	"bufio"
	"fmt"
	. "github.com/whereswaldon/slijkstra/alg"
	"io"
	"os"
	"strconv"
	"strings"
)

// exit wraps an exit code with a type
type exit struct {
	Code int
}

// handleExit recovers from panics and checks whether the
// panic was caused by an exit request. If it was, it exits
// with that status code. Otherwise, it panics again.
func handleExit() {
	if r := recover(); r != nil {
		if e, ok := r.(exit); !ok {
			panic(r)
		} else {
			os.Exit(e.Code)
		}
	}
}

// setupGraph parses the file contents and creates a graph
// representing the file
func setupGraph(filename string) *Graph {
	fmt.Println("Opening", filename)
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("Unable to open file! ", err)
		panic(exit{1})
	}
	defer file.Close()
	buffReader := bufio.NewReader(file)
	nodes, err := buffReader.ReadString('\n')
	if err != nil {
		fmt.Println("Unable to read line! ", err)
		panic(exit{1})
	}
	nodes = strings.TrimSpace(nodes)
	order, err := strconv.Atoi(nodes)
	if err != nil {
		fmt.Println("Unable to convert nodes to integer")
		panic(exit{1})
	}
	graph := NewGraph(order)
	fmt.Println("There are", nodes, "nodes in the graph!")
	var u, v, weight int
	var line string
	for err == nil || err != io.EOF {
		line, err = buffReader.ReadString('\n')
		fmt.Sscanf(line, "%d %d %d\n", &u, &v, &weight)
		graph.InsertEdge(u, v, weight)
	}
	return graph
}

func main() {
	defer handleExit()
	var root int = 0
	var err error
	if len(os.Args) < 2 {
		fmt.Println("Please supply a filename as an argument")
		panic(exit{1})
	} else if len(os.Args) < 3 {
		fmt.Println("No root node specified, defaulting to zero")
	} else {
		root, err = strconv.Atoi(os.Args[2])
		if err != nil {
			fmt.Println("Unable to convert second argument to number: ", err)
			panic(exit{1})
		}
	}

	graph := setupGraph(os.Args[1])
	table := graph.FindShortestPathTree(root)

	fmt.Println(table)
	fmt.Println("Max distance: ", table.MaxDistance, " from ", table.Root, " to ", table.FurthestNode)
	s, e, d := graph.FindDiameter()
	fmt.Println("diameter: ", d, " start: ", s, " end: ", e)
}
<|endoftext|>


<commit_before>package main

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

	"bufio"

	"io"

	"github.com/gorilla/mux"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	defaultPayloadFilename = "test_payload"
	defaultTimeout         = "5s"
)

var (
	payloadFile       *os.File
	payloadFileLength int64
	outgoingClient    = &http.Client{}
	protocol          = "http"

	//COMMAND LINE STUFF
	cmdline         = kingpin.New("cf-http-payload-tester", "Test your HTTP requests on Cloud Foundry")
	timeout         = cmdline.Flag("timeout", "Time in seconds to wait for response to check calls").Short('t').Default(defaultTimeout).Duration()
	useHTTPS        = cmdline.Flag("https-out", "Use https in outbound URL instead of http").Short('s').Bool()
	payloadFilename = cmdline.Flag("payload", "Target payload file").Short('p').Default(defaultPayloadFilename).String()
)

func main() {
	cmdline.HelpFlag.Short('h')
	kingpin.MustParse(cmdline.Parse(os.Args[1:]))

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

	err = launchAPIServer()
	log.Fatal(err.Error())
}

func setup() (err error) {
	//Get the file to send over HTTP
	payloadFile, err = os.Open(fmt.Sprintf("%s", *payloadFilename))
	if err != nil {
		return fmt.Errorf("Could not open payload file: %s", err.Error())
	}

	//Get length of file for reporting
	stats, err := payloadFile.Stat()
	if err != nil {
		return fmt.Errorf("error stat-ing file: %s", err.Error())
	}

	payloadFileLength = stats.Size()

	//Make sure the PORT env var is set
	if os.Getenv("PORT") == "" {
		return fmt.Errorf("Please set PORT environment variable with port for server to listen on")
	}

	//Make sure that PORT is numeric
	_, err = strconv.Atoi(os.Getenv("PORT"))
	if err != nil {
		return fmt.Errorf("PORT environment variable was not numeric")
	}

	log.Printf("Setting HTTP client timeout to %s", *timeout)
	outgoingClient.Timeout = *timeout

	if *useHTTPS {
		protocol = "https"
	}
	log.Printf("Setting protocol to %s", protocol)

	return nil
}

func launchAPIServer() error {
	router := mux.NewRouter()
	router.HandleFunc("/check/{route}", checkHandler).Methods("GET")
	router.HandleFunc("/listen", listenHandler).Methods("POST")
	router.HandleFunc("/pull", pullHandler).Methods("GET")

	return http.ListenAndServe(fmt.Sprintf(":%s", os.Getenv("PORT")), router)
}

type responseJSON struct {
	Status       *int   `json:"status,omitempty"`
	ErrorMessage string `json:"error,omitempty"`
	Bytes        *int64 `json:"bytes"`
}

func responsify(r *responseJSON) []byte {
	ret, err := json.Marshal(r)
	if err != nil {
		panic("Couldn't marshal JSON")
	}
	return ret
}

func checkHandler(w http.ResponseWriter, r *http.Request) {
	outgoingResp := &responseJSON{Bytes: &payloadFileLength}
	route := mux.Vars(r)["route"]
	//Make our outgoing POST request to send to the other app
	outgoingRequest, err := http.NewRequest("POST", fmt.Sprintf("%s://%s/listen", protocol, route), bufio.NewReader(payloadFile))
	if err != nil {
		panic("Could not form http request")
	}
	//Set the Content-Type and if X-Payload-Tracer is given, put that in too
	outgoingRequest.Header.Set("Content-Type", "text/plain")
	outgoingRequest.Header.Set("X-Payload-Tracer", r.Header.Get("X-Payload-Tracer"))

	resp, err := outgoingClient.Do(outgoingRequest)

	//Reset payload file seek position to the start of the file
	defer func() {
		_, err = payloadFile.Seek(0, io.SeekStart)
		if err != nil {
			panic("Could not reset payload file seek position")
		}
	}()

	if err != nil {
		outgoingResp.ErrorMessage = fmt.Sprintf("Error while sending request: %s", err)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(responsify(outgoingResp))
		return
	}

	//Not sure this can even happen... but...
	if resp.StatusCode != 200 {
		outgoingResp.ErrorMessage = fmt.Sprintf("Non 200-code returned from request to listening server: %d", resp.StatusCode)
	}

	w.WriteHeader(resp.StatusCode)
	outgoingResp.Status = &resp.StatusCode
	w.Write(responsify(outgoingResp))
}

func listenHandler(w http.ResponseWriter, r *http.Request) {
	//I mean... TCP guarantees that if we're this far, the body is correct
	// So.... if we got this far, the payload was successfully sent
	w.WriteHeader(http.StatusOK)
}

func pullHandler(w http.ResponseWriter, r *http.Request) {
	var err error
	//Reset payload file seek position to the start of the file
	defer func() {
		_, err = payloadFile.Seek(0, io.SeekStart)
		if err != nil {
			panic("Could not reset payload file seek position")
		}
	}()

	//Gotta take the file in in chunks so that we don't blow up the RAM if
	// somebody tests with a huge file.
	const bufferSize = 8 * 1024 //8KiB please
	buffer := make([]byte, bufferSize)
	var bytesRead = bufferSize //Initial value to kick off the while loop
	for bytesRead == bufferSize && err != io.EOF {
		bytesRead, err = payloadFile.Read(buffer)
		w.Write(buffer[:bytesRead])
	}
}
<commit_msg>Guarantee sychronous http response<commit_after>package main

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

	"bufio"

	"io"

	"github.com/gorilla/mux"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	defaultPayloadFilename = "test_payload"
	defaultTimeout         = "5s"
)

var (
	payloadFile       *os.File
	payloadFileLength int64
	outgoingClient    = &http.Client{}
	protocol          = "http"

	//COMMAND LINE STUFF
	cmdline         = kingpin.New("cf-http-payload-tester", "Test your HTTP requests on Cloud Foundry")
	timeout         = cmdline.Flag("timeout", "Time in seconds to wait for response to check calls").Short('t').Default(defaultTimeout).Duration()
	useHTTPS        = cmdline.Flag("https-out", "Use https in outbound URL instead of http").Short('s').Bool()
	payloadFilename = cmdline.Flag("payload", "Target payload file").Short('p').Default(defaultPayloadFilename).String()
)

func main() {
	cmdline.HelpFlag.Short('h')
	kingpin.MustParse(cmdline.Parse(os.Args[1:]))

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

	err = launchAPIServer()
	log.Fatal(err.Error())
}

func setup() (err error) {
	//Get the file to send over HTTP
	payloadFile, err = os.Open(fmt.Sprintf("%s", *payloadFilename))
	if err != nil {
		return fmt.Errorf("Could not open payload file: %s", err.Error())
	}

	//Get length of file for reporting
	stats, err := payloadFile.Stat()
	if err != nil {
		return fmt.Errorf("error stat-ing file: %s", err.Error())
	}

	payloadFileLength = stats.Size()

	//Make sure the PORT env var is set
	if os.Getenv("PORT") == "" {
		return fmt.Errorf("Please set PORT environment variable with port for server to listen on")
	}

	//Make sure that PORT is numeric
	_, err = strconv.Atoi(os.Getenv("PORT"))
	if err != nil {
		return fmt.Errorf("PORT environment variable was not numeric")
	}

	log.Printf("Setting HTTP client timeout to %s", *timeout)
	outgoingClient.Timeout = *timeout

	if *useHTTPS {
		protocol = "https"
	}
	log.Printf("Setting protocol to %s", protocol)

	return nil
}

func launchAPIServer() error {
	router := mux.NewRouter()
	router.HandleFunc("/check/{route}", checkHandler).Methods("GET")
	router.HandleFunc("/listen", listenHandler).Methods("POST")
	router.HandleFunc("/pull", pullHandler).Methods("GET")

	return http.ListenAndServe(fmt.Sprintf(":%s", os.Getenv("PORT")), router)
}

type responseJSON struct {
	Status       *int   `json:"status,omitempty"`
	ErrorMessage string `json:"error,omitempty"`
	Bytes        *int64 `json:"bytes"`
}

func responsify(r *responseJSON) []byte {
	ret, err := json.Marshal(r)
	if err != nil {
		panic("Couldn't marshal JSON")
	}
	return ret
}

func checkHandler(w http.ResponseWriter, r *http.Request) {
	outgoingResp := &responseJSON{Bytes: &payloadFileLength}
	route := mux.Vars(r)["route"]
	//Make our outgoing POST request to send to the other app
	outgoingRequest, err := http.NewRequest("POST", fmt.Sprintf("%s://%s/listen", protocol, route), bufio.NewReader(payloadFile))
	if err != nil {
		panic("Could not form http request")
	}
	//Set the Content-Type and if X-Payload-Tracer is given, put that in too
	outgoingRequest.Header.Set("Content-Type", "text/plain")
	outgoingRequest.Header.Set("X-Payload-Tracer", r.Header.Get("X-Payload-Tracer"))

	resp, err := outgoingClient.Do(outgoingRequest)

	//Reset payload file seek position to the start of the file
	defer func() {
		_, err = payloadFile.Seek(0, io.SeekStart)
		if err != nil {
			panic("Could not reset payload file seek position")
		}
	}()

	if err != nil {
		outgoingResp.ErrorMessage = fmt.Sprintf("Error while sending request: %s", err)
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(responsify(outgoingResp))
		return
	}

	if resp.StatusCode == 500 {
		outgoingResp.ErrorMessage = fmt.Sprintf("Remote server failed while reading request body")
	}

	w.WriteHeader(resp.StatusCode)
	outgoingResp.Status = &resp.StatusCode
	w.Write(responsify(outgoingResp))
}

func listenHandler(w http.ResponseWriter, r *http.Request) {
	_, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
	}
	w.WriteHeader(http.StatusOK)
}

func pullHandler(w http.ResponseWriter, r *http.Request) {
	var err error
	//Reset payload file seek position to the start of the file
	defer func() {
		_, err = payloadFile.Seek(0, io.SeekStart)
		if err != nil {
			panic("Could not reset payload file seek position")
		}
	}()

	//Gotta take the file in in chunks so that we don't blow up the RAM if
	// somebody tests with a huge file.
	const bufferSize = 8 * 1024 //8KiB please
	buffer := make([]byte, bufferSize)
	var bytesRead = bufferSize //Initial value to kick off the while loop
	for bytesRead == bufferSize && err != io.EOF {
		bytesRead, err = payloadFile.Read(buffer)
		w.Write(buffer[:bytesRead])
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"fmt"
	"log"
	"math/big"
	"time"

	"github.com/y0ssar1an/slack-pushups/internal/slack"
)

const (
	minPushUps  = 10
	maxPushUps  = 30
	openingHour = 10
	closingHour = 18
)

func main() {
	// fail early if zoneinfo db not present on server
	loc, err := time.LoadLocation("America/Los_Angeles")
	if err != nil {
		log.Fatal(err)
	}

	ch, err := slack.NewChannel("api-test")
	if err != nil {
		log.Fatal(err)
	}

	// start async routine that chooses users randomly for push-ups
	nextMemberID := make(chan string)
	go randomMember(ch, nextMemberID)

	SgtMittens := slack.Bot{"SgtMitt"}

	for {
		now := time.Now().In(loc)
		if closed, timeToOpen := isAfterHours(now, loc); closed {
			time.Sleep(timeToOpen)
			SgtMittens.PostMessage("RISE AND SHINE, CUPCAKES!", ch)
		}

		var user slack.User
		for user.Name == "" {
			user, err = slack.NewUser(<-nextMemberID)
			if err != nil {
				log.Println(err)
				time.Sleep(1 * time.Minute)
			}
		}

		pushUps := randInt(minPushUps, maxPushUps+1) // +1 because upper bound is non-inclusive
		msg := fmt.Sprintf(
			"@%s %d PUSH-UPS RIGHT MEOW!",
			user.Name,
			pushUps,
		)

		if !closingSoon(now, loc) {
			msg += "\nNext lottery for push-ups in 20 minutes"
		}

		err = SgtMittens.PostMessage(msg, ch)
		if err != nil {
			log.Println(err)
			time.Sleep(1 * time.Minute)
			continue
		}
		time.Sleep(20 * time.Minute)
	}
}

func randomMember(ch slack.Channel, nextMemberID chan string) {
	var err error
	for {
		err = ch.UpdateMembers()
		if err != nil {
			log.Println(err)
		}

		i := randInt(0, len(ch.Members))
		nextMemberID <- ch.Members[i]
	}
}

func randInt(min, max int) int {
	n, err := rand.Int(rand.Reader, big.NewInt(int64(max-min)))
	if err != nil {
		log.Println(err)
	}
	// return min if rand.Int() call fails
	return int(n.Int64()) + min
}

func isAfterHours(now time.Time, loc *time.Location) (bool, time.Duration) {
	var timeToOpen time.Duration

	if isWeekend(now) {
		days := daysToMonday(now.Weekday())
		mondayOpeningTime := time.Date(now.Year(), now.Month(), now.Day()+days, openingHour, 0, 0, 0, loc)
		timeToOpen = mondayOpeningTime.Sub(now)
		return true, timeToOpen
	}

	if now.Hour() < openingHour {
		openToday := time.Date(now.Year(), now.Month(), now.Day(), openingHour, 0, 0, 0, loc)
		timeToOpen = openToday.Sub(now)
		return true, timeToOpen
	}

	if now.Hour() >= closingHour {
		openTomorrow := time.Date(now.Year(), now.Month(), now.Day()+1, openingHour, 0, 0, 0, loc)
		timeToOpen = openTomorrow.Sub(now)
		return true, timeToOpen
	}

	return false, timeToOpen // 0 time
}

func isWeekend(t time.Time) bool {
	day := t.Weekday()
	return (day == time.Friday && t.Hour() >= closingHour) || day == time.Saturday || day == time.Sunday
}

func daysToMonday(day time.Weekday) int {
	const weekdays = 7
	return (weekdays - int(day-time.Monday)) % weekdays
}

// Return true if closing time is in less than 20 minutes.
func closingSoon(now time.Time, loc *time.Location) bool {
	closingTime := time.Date(now.Year(), now.Month(), now.Day(), closingHour, 0, 0, 0, loc)
	return closingTime.Sub(now) <= (20 * time.Minute)
}
<commit_msg>Capitalize main functions and write doc comments for all funcs<commit_after>package main

import (
	"crypto/rand"
	"fmt"
	"log"
	"math/big"
	"time"

	"github.com/y0ssar1an/slack-pushups/internal/slack"
)

const (
	minPushUps  = 10
	maxPushUps  = 30
	openingHour = 10
	closingHour = 18
)

func main() {
	// fail early if zoneinfo db not present on server
	loc, err := time.LoadLocation("America/Los_Angeles")
	if err != nil {
		log.Fatal(err)
	}

	ch, err := slack.NewChannel("api-test")
	if err != nil {
		log.Fatal(err)
	}

	// start async routine that chooses users randomly for push-ups
	nextMemberID := make(chan string)
	go RandomMember(ch, nextMemberID)

	SgtMittens := slack.Bot{"SgtMitt"}

	for {
		now := time.Now().In(loc)
		if closed, timeToOpen := IsAfterHours(now, loc); closed {
			time.Sleep(timeToOpen)
			SgtMittens.PostMessage("RISE AND SHINE, CUPCAKES!", ch)
		}

		var user slack.User
		for user.Name == "" {
			user, err = slack.NewUser(<-nextMemberID)
			if err != nil {
				log.Println(err)
				time.Sleep(1 * time.Minute)
			}
		}

		pushUps := RandInt(minPushUps, maxPushUps+1) // +1 because upper bound is non-inclusive
		msg := fmt.Sprintf(
			"@%s %d PUSH-UPS RIGHT MEOW!",
			user.Name,
			pushUps,
		)

		if !ClosingSoon(now, loc) {
			msg += "\nNext lottery for push-ups in 20 minutes"
		}

		err = SgtMittens.PostMessage(msg, ch)
		if err != nil {
			log.Println(err)
			time.Sleep(1 * time.Minute)
			continue
		}
		time.Sleep(20 * time.Minute)
	}
}

// RandomMember updates the list of members in the given Slack channel and
// returns a random member ID.
func RandomMember(ch slack.Channel, nextMemberID chan string) {
	var err error
	for {
		err = ch.UpdateMembers()
		if err != nil {
			log.Println(err)
		}

		i := RandInt(0, len(ch.Members))
		nextMemberID <- ch.Members[i]
	}
}

// RandInt uses /dev/urandom to select a random integer in the range [min, max).
func RandInt(min, max int) int {
	n, err := rand.Int(rand.Reader, big.NewInt(int64(max-min)))
	if err != nil {
		log.Println(err)
	}

	return int(n.Int64()) + min // return min if rand.Int() call fails
}

// IsAfterHours returns true if the given time is after work hours at Omaze.
// If Omaze is closed, IsAfterHours will return the duration until opening time
// on Monday.
func IsAfterHours(now time.Time, loc *time.Location) (closed bool, timeToOpen time.Duration) {
	if IsWeekend(now) {
		days := DaysToMonday(now.Weekday())
		mondayOpeningTime := time.Date(now.Year(), now.Month(), now.Day()+days, openingHour, 0, 0, 0, loc)
		timeToOpen = mondayOpeningTime.Sub(now)
		return true, timeToOpen
	}

	if now.Hour() < openingHour {
		openToday := time.Date(now.Year(), now.Month(), now.Day(), openingHour, 0, 0, 0, loc)
		timeToOpen = openToday.Sub(now)
		return true, timeToOpen
	}

	if now.Hour() >= closingHour {
		openTomorrow := time.Date(now.Year(), now.Month(), now.Day()+1, openingHour, 0, 0, 0, loc)
		timeToOpen = openTomorrow.Sub(now)
		return true, timeToOpen
	}

	return false, timeToOpen // 0 time
}

// IsWeekend returns true if the given time is Friday after closing time,
// Saturday, or Sunday.
func IsWeekend(t time.Time) bool {
	day := t.Weekday()
	return (day == time.Friday && t.Hour() >= closingHour) || day == time.Saturday || day == time.Sunday
}

// DaysToMonday returns the number of days from the given weekday to Monday.
func DaysToMonday(day time.Weekday) int {
	const weekdays = 7
	return (weekdays - int(day-time.Monday)) % weekdays
}

// ClosingSoon returns true if the given time is within 20 minutes of closing
// time.
func ClosingSoon(now time.Time, loc *time.Location) bool {
	closingTime := time.Date(now.Year(), now.Month(), now.Day(), closingHour, 0, 0, 0, loc)
	return closingTime.Sub(now) <= (20 * time.Minute)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"

	"sync"

	"sort"

	"github.com/BurntSushi/toml"
	"github.com/k0pernicus/goyave/configurationFile"
	"github.com/k0pernicus/goyave/consts"
	"github.com/k0pernicus/goyave/traces"
	"github.com/k0pernicus/goyave/utils"
	"github.com/k0pernicus/goyave/walk"
	"github.com/spf13/cobra"
)

var configurationFileStructure configurationFile.ConfigurationFile
var configurationFilePath string
var userHomeDir string

/*initialize get the configuration file existing in the system (or create it), and return
 *a pointer to his content.
 */
func initialize(configurationFileStructure *configurationFile.ConfigurationFile) {
	// Initialize all different traces structures
	traces.InitTraces(os.Stdout, os.Stderr, os.Stdout, os.Stdout)

	// Get the user home directory
	userHomeDir = utils.GetUserHomeDir()
	if len(userHomeDir) == 0 {
		log.Fatalf("Cannot get the user home dir.\n")
	}
	// Set the configuration path file
	configurationFilePath = path.Join(userHomeDir, consts.ConfigurationFileName)
	filePointer, err := os.OpenFile(configurationFilePath, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		log.Fatalf("Cannot open the file %s, due to error '%s'.\n", configurationFilePath, err)
	}
	defer filePointer.Close()
	var bytesArray []byte
	// Get the content of the goyave configuration file
	configurationFile.GetConfigurationFileContent(filePointer, &bytesArray)
	if _, err = toml.Decode(string(bytesArray[:]), configurationFileStructure); err != nil {
		log.Fatalln(err)
	}
}

/*kill saves the current state of the configuration structure in the configuration file
 */
func kill() {
	var outputBuffer bytes.Buffer
	if err := configurationFileStructure.Encode(&outputBuffer); err != nil {
		log.Fatalln("Cannot save the current configurationFile structure!")
	}
	if err := ioutil.WriteFile(configurationFilePath, outputBuffer.Bytes(), 0777); err != nil {
		log.Fatalln("Cannot access to your file to save the configurationFile structure!")
	}
}

func main() {

	/*rootCmd defines the global app, and some actions to run before and after the command running
	 */
	var rootCmd = &cobra.Command{
		Use:   "goyave",
		Short: "Goyave is a tool to take a look at your local git repositories",
		// Initialize the structure
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			initialize(&configurationFileStructure)
		},
		// Save the current configuration file structure, in the configuration file
		PersistentPostRun: func(cmd *cobra.Command, args []string) {
			kill()
		},
	}

	/*addCmd is a subcommand to add the current working directory as a VISIBLE one
	 */
	var addCmd = &cobra.Command{
		Use:   "add",
		Short: "Add the current path as a VISIBLE repository",
		Run: func(cmd *cobra.Command, args []string) {
			// Get the path where the command has been executed
			currentDir, err := os.Getwd()
			if err != nil {
				log.Fatalln("There was a problem retrieving the current directory")
			}
			if !utils.IsGitRepository(currentDir) {
				log.Fatalf("%s is not a git repository!\n", currentDir)
			}
			// If the path is/contains a .git directory, add this one as a VISIBLE repository
			if err := configurationFileStructure.AddRepository(currentDir, consts.VisibleFlag); err != nil {
				traces.WarningTracer.Printf("[%s] %s\n", currentDir, err)
			}
		},
	}

	/*crawlCmd is a subcommand to crawl your hard drive in order to get and save new git repositories
	 */
	var crawlCmd = &cobra.Command{
		Use:   "crawl",
		Short: "Crawl the hard drive in order to find git repositories",
		Run: func(cmd *cobra.Command, args []string) {
			var wg sync.WaitGroup
			// Get all git paths, and display them
			gitPaths, err := walk.RetrieveGitRepositories(userHomeDir)
			if err != nil {
				log.Fatalf("There was an error retrieving your git repositories: '%s'\n", err)
			}
			// For each git repository, check if it exists, and if not add it to the default target visibility
			for _, gitPath := range gitPaths {
				wg.Add(1)
				go func(gitPath string) {
					defer wg.Done()
					if err := configurationFileStructure.AddRepository(gitPath, configurationFileStructure.Local.DefaultTarget); err != nil {
						traces.WarningTracer.Printf("[%s] %s\n", gitPath, err)
					}
				}(gitPath)
			}
			wg.Wait()
		},
	}

	/*stateCmd is a subcommand to list the state of each local git repository.
	 */
	var stateCmd = &cobra.Command{
		Use:     "state",
		Example: "goyave state\ngoyave state myRepositoryName\ngoyave state myRepositoryName1 myRepositoryName2",
		Short:   "Get the state of each local visible git repository",
		Long:    "Check only visible git repositories.\nIf some repository names have been setted, goyave will only check those repositories, otherwise it checks all visible repositories of your system.",
		Run: func(cmd *cobra.Command, args []string) {
			var gitStructs []configurationFile.GitRepository
			if len(args) == 0 {
				gitStructs = configurationFileStructure.VisibleRepositories
			} else {
				// Sort visible repositories by name
				sort.Sort(configurationFile.ByName(configurationFileStructure.VisibleRepositories))
				repositoriesListLength := len(configurationFileStructure.VisibleRepositories)
				// Looking for given repository names - if the looking one does not exists, let the function prints a warning message.
				for _, repositoryName := range args {
					repositoryIndex := sort.Search(repositoriesListLength, func(i int) bool { return configurationFileStructure.VisibleRepositories[i].Name >= repositoryName })
					if repositoryIndex != repositoriesListLength {
						gitStructs = append(gitStructs, configurationFileStructure.VisibleRepositories[repositoryIndex])
					} else {
						traces.WarningTracer.Printf("%s cannot be found in your visible repositories!\n", repositoryName)
					}
				}
			}
			var wg sync.WaitGroup
			for _, gitStruct := range gitStructs {
				wg.Add(1)
				go func(gitStruct configurationFile.GitRepository) {
					defer wg.Done()
					gitStruct.Init()
					gitStruct.GitObject.Status()
				}(gitStruct)
			}
			wg.Wait()
		},
	}

	/*switchCmd is a subcommand to switch the visibility of the current git repository.
	 */
	var switchCmd = &cobra.Command{
		Use:   "switch",
		Short: "Switch the visibility of the current git repository (given by the current path)",
		Run: func(cmd *cobra.Command, args []string) {
			// Get the path where the command has been executed
			currentDir, err := os.Getwd()
			if err != nil {
				log.Fatalln("There was a problem retrieving the current directory")
			}
			if err := configurationFileStructure.RemoveRepositoryFromSlice(currentDir, consts.VisibleFlag); err == nil {
				configurationFileStructure.AddRepository(currentDir, consts.HiddenFlag)
				traces.InfoTracer.Printf("%s has been set to an hidden repository!", currentDir)
				return
			}
			if err := configurationFileStructure.RemoveRepositoryFromSlice(currentDir, consts.HiddenFlag); err == nil {
				configurationFileStructure.AddRepository(currentDir, consts.VisibleFlag)
				traces.InfoTracer.Printf("%s has been set to a visible repository!", currentDir)
				return
			}
			log.Fatalf("The repository %s is not saved as a VISIBLE or HIDDEN repository! Please to add it before.\n", currentDir)
		},
	}

	rootCmd.AddCommand(addCmd, crawlCmd, stateCmd, switchCmd)

	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<commit_msg>Add the path command<commit_after>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"

	"sync"

	"sort"

	"github.com/BurntSushi/toml"
	"github.com/k0pernicus/goyave/configurationFile"
	"github.com/k0pernicus/goyave/consts"
	"github.com/k0pernicus/goyave/traces"
	"github.com/k0pernicus/goyave/utils"
	"github.com/k0pernicus/goyave/walk"
	"github.com/spf13/cobra"
)

var configurationFileStructure configurationFile.ConfigurationFile
var configurationFilePath string
var userHomeDir string

/*initialize get the configuration file existing in the system (or create it), and return
 *a pointer to his content.
 */
func initialize(configurationFileStructure *configurationFile.ConfigurationFile) {
	// Initialize all different traces structures
	traces.InitTraces(os.Stdout, os.Stderr, os.Stdout, os.Stdout)

	// Get the user home directory
	userHomeDir = utils.GetUserHomeDir()
	if len(userHomeDir) == 0 {
		log.Fatalf("Cannot get the user home dir.\n")
	}
	// Set the configuration path file
	configurationFilePath = path.Join(userHomeDir, consts.ConfigurationFileName)
	filePointer, err := os.OpenFile(configurationFilePath, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		log.Fatalf("Cannot open the file %s, due to error '%s'.\n", configurationFilePath, err)
	}
	defer filePointer.Close()
	var bytesArray []byte
	// Get the content of the goyave configuration file
	configurationFile.GetConfigurationFileContent(filePointer, &bytesArray)
	if _, err = toml.Decode(string(bytesArray[:]), configurationFileStructure); err != nil {
		log.Fatalln(err)
	}
}

/*kill saves the current state of the configuration structure in the configuration file
 */
func kill() {
	var outputBuffer bytes.Buffer
	if err := configurationFileStructure.Encode(&outputBuffer); err != nil {
		log.Fatalln("Cannot save the current configurationFile structure!")
	}
	if err := ioutil.WriteFile(configurationFilePath, outputBuffer.Bytes(), 0777); err != nil {
		log.Fatalln("Cannot access to your file to save the configurationFile structure!")
	}
}

func main() {

	/*rootCmd defines the global app, and some actions to run before and after the command running
	 */
	var rootCmd = &cobra.Command{
		Use:   "goyave",
		Short: "Goyave is a tool to take a look at your local git repositories",
		// Initialize the structure
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			initialize(&configurationFileStructure)
		},
		// Save the current configuration file structure, in the configuration file
		PersistentPostRun: func(cmd *cobra.Command, args []string) {
			kill()
		},
	}

	/*addCmd is a subcommand to add the current working directory as a VISIBLE one
	 */
	var addCmd = &cobra.Command{
		Use:   "add",
		Short: "Add the current path as a VISIBLE repository",
		Run: func(cmd *cobra.Command, args []string) {
			// Get the path where the command has been executed
			currentDir, err := os.Getwd()
			if err != nil {
				log.Fatalln("There was a problem retrieving the current directory")
			}
			if !utils.IsGitRepository(currentDir) {
				log.Fatalf("%s is not a git repository!\n", currentDir)
			}
			// If the path is/contains a .git directory, add this one as a VISIBLE repository
			if err := configurationFileStructure.AddRepository(currentDir, consts.VisibleFlag); err != nil {
				traces.WarningTracer.Printf("[%s] %s\n", currentDir, err)
			}
		},
	}

	/*crawlCmd is a subcommand to crawl your hard drive in order to get and save new git repositories
	 */
	var crawlCmd = &cobra.Command{
		Use:   "crawl",
		Short: "Crawl the hard drive in order to find git repositories",
		Run: func(cmd *cobra.Command, args []string) {
			var wg sync.WaitGroup
			// Get all git paths, and display them
			gitPaths, err := walk.RetrieveGitRepositories(userHomeDir)
			if err != nil {
				log.Fatalf("There was an error retrieving your git repositories: '%s'\n", err)
			}
			// For each git repository, check if it exists, and if not add it to the default target visibility
			for _, gitPath := range gitPaths {
				wg.Add(1)
				go func(gitPath string) {
					defer wg.Done()
					if err := configurationFileStructure.AddRepository(gitPath, configurationFileStructure.Local.DefaultTarget); err != nil {
						traces.WarningTracer.Printf("[%s] %s\n", gitPath, err)
					}
				}(gitPath)
			}
			wg.Wait()
		},
	}

	/*stateCmd is a subcommand to list the state of each local git repository.
	 */
	var stateCmd = &cobra.Command{
		Use:     "state",
		Example: "goyave state\ngoyave state myRepositoryName\ngoyave state myRepositoryName1 myRepositoryName2",
		Short:   "Get the state of each local visible git repository",
		Long:    "Check only visible git repositories.\nIf some repository names have been setted, goyave will only check those repositories, otherwise it checks all visible repositories of your system.",
		Run: func(cmd *cobra.Command, args []string) {
			var gitStructs []configurationFile.GitRepository
			if len(args) == 0 {
				gitStructs = configurationFileStructure.VisibleRepositories
			} else {
				// Sort visible repositories by name
				sort.Sort(configurationFile.ByName(configurationFileStructure.VisibleRepositories))
				repositoriesListLength := len(configurationFileStructure.VisibleRepositories)
				// Looking for given repository names - if the looking one does not exists, let the function prints a warning message.
				for _, repositoryName := range args {
					repositoryIndex := sort.Search(repositoriesListLength, func(i int) bool { return configurationFileStructure.VisibleRepositories[i].Name >= repositoryName })
					if repositoryIndex != repositoriesListLength {
						gitStructs = append(gitStructs, configurationFileStructure.VisibleRepositories[repositoryIndex])
					} else {
						traces.WarningTracer.Printf("%s cannot be found in your visible repositories!\n", repositoryName)
					}
				}
			}
			var wg sync.WaitGroup
			for _, gitStruct := range gitStructs {
				wg.Add(1)
				go func(gitStruct configurationFile.GitRepository) {
					defer wg.Done()
					gitStruct.Init()
					gitStruct.GitObject.Status()
				}(gitStruct)
			}
			wg.Wait()
		},
	}

	var pathCmd = &cobra.Command{
		Use:   "path",
		Short: "Get the path of a given repository, if this one exists",
		Run: func(cmd *cobra.Command, args []string) {
			if len(args) == 0 {
				log.Fatalln("Needs a repository name!")
			}
			repo := args[0]
			repoPath := configurationFileStructure.GetPathFromRepository(repo)
			if repoPath != "" {
				fmt.Println(repoPath)
			} else {
				log.Fatalf("The repository %s does not exists!\n", repo)
			}
		},
	}

	/*switchCmd is a subcommand to switch the visibility of the current git repository.
	 */
	var switchCmd = &cobra.Command{
		Use:   "switch",
		Short: "Switch the visibility of the current git repository (given by the current path)",
		Run: func(cmd *cobra.Command, args []string) {
			// Get the path where the command has been executed
			currentDir, err := os.Getwd()
			if err != nil {
				log.Fatalln("There was a problem retrieving the current directory")
			}
			if err := configurationFileStructure.RemoveRepositoryFromSlice(currentDir, consts.VisibleFlag); err == nil {
				configurationFileStructure.AddRepository(currentDir, consts.HiddenFlag)
				traces.InfoTracer.Printf("%s has been set to an hidden repository!", currentDir)
				return
			}
			if err := configurationFileStructure.RemoveRepositoryFromSlice(currentDir, consts.HiddenFlag); err == nil {
				configurationFileStructure.AddRepository(currentDir, consts.VisibleFlag)
				traces.InfoTracer.Printf("%s has been set to a visible repository!", currentDir)
				return
			}
			log.Fatalf("The repository %s is not saved as a VISIBLE or HIDDEN repository! Please to add it before.\n", currentDir)
		},
	}

	rootCmd.AddCommand(addCmd, crawlCmd, pathCmd, stateCmd, switchCmd)

	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"./model"
	"github.com/rs/cors"
	"goji.io"
	"goji.io/pat"
	"golang.org/x/net/context"
	mgo "gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

func main() {
	//trying to connect to mongo
	db, err := mgo.Dial("localhost:27017")
	if err != nil {
		//something happens when dialing
		log.Fatal("Cannot dial mongo", err)
	}
	//clear when we're done
	defer db.Close()
	ensureIndex(db)
	//initiate new multiplexer
	mux := goji.NewMux()
	//register all handler for each end point
	mux.HandleFuncC(pat.Get("/swits/:switId"), getSwit(db))
	mux.HandleFuncC(pat.Get("/swits"), getAllSwits(db))
	mux.HandleFuncC(pat.Post("/swits"), createSwit(db))
	mux.HandleFuncC(pat.Post("/users"), addUser(db))
	mux.HandleFuncC(pat.Get("/users/:uid"), getUser(db))
	//to allow cross origin
	handler := cors.Default().Handler(mux)
	//finally, listen and serve in designated host and port
	http.ListenAndServe("localhost:3001", handler)
}

func ensureIndex(s *mgo.Session) {
	session := s.Copy()
	defer session.Close()

	c := session.DB("swit_app").C("users")

	index := mgo.Index{
		Key:        []string{"uid"},
		Unique:     true,
		DropDups:   true,
		Background: true,
		Sparse:     true,
	}
	err := c.EnsureIndex(index)
	if err != nil {
		log.Fatal(err)
	}
}

func addUser(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get the body request
		var user model.User
		decoder := json.NewDecoder(req.Body)
		err := decoder.Decode(&user)
		if err != nil {
			fmt.Println("Incorrect body of request")
			return
		}
		c := session.DB("swit_app").C("users")
		//add new user to database
		err = c.Insert(user)
		if err != nil {
			if mgo.IsDup(err) {
				//check if it's duplicate, if so return something to notify
				ResponseSimpleMessage("User is exist", false, w)
				return
			}
			//failed to Insert
			fmt.Println("Failed to insert a new user")
			log.Fatal(err)
		}

		ResponseSimpleMessage("Successfully added a new user", true, w)
	}
}

func getUser(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get query param
		uid := pat.Param(ctx, "uid")
		//get collection of users
		c := session.DB("swit_app").C("users")
		//prepare the model
		var user model.User
		//fetch the user in db
		err := c.Find(bson.M{"uid": uid}).One(&user)
		if err != nil {
			//failed to Insert
			fmt.Printf("Unable to search user with uid: %s", uid)
			log.Fatal(err)
		}
		//toJson
		respBody, _ := json.Marshal(user)
		ResponseWithJSON(w, respBody, http.StatusOK)
	}
}

func createSwit(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get the body request
		var swit model.Swit
		decoder := json.NewDecoder(req.Body)
		err := decoder.Decode(&swit)
		if err != nil {
			fmt.Println("Incorrect body of request")
			return
		}

		//should be now
		swit.Time = time.Now()
		swit.SwitId = bson.NewObjectIdWithTime(swit.Time)
		//TODO: should get the user id from req too
		swit.UserId = bson.NewObjectId()
		fmt.Println("incoming swit: ", swit)

		c := session.DB("swit_app").C("swits")
		//insert the new swit and catch error
		err = c.Insert(swit)
		if err != nil {
			//failed to Insert
			fmt.Println("Failed to insert a new book")
			log.Fatal(err)
		}
		resBody := SimpleResponse{"Successfully added a new book", true}
		fmt.Println("res body content: ", resBody)
		//toJson
		json, _ := json.Marshal(resBody)
		//write a response back
		ResponseWithJSON(w, json, http.StatusOK)
	}
}

func getAllSwits(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//prepare for the response
		var swits []*model.Swit
		//catch them all and if there is an error
		err := session.DB("swit_app").C("swits").Find(nil).All(&swits)
		if err != nil {
			//let's get panic instead
			panic(err)
		}
		// _ as blank identifier,the function returns multiple values, but we don't care
		switsJSON, _ := json.Marshal(swits)
		//write a response
		ResponseWithJSON(w, switsJSON, http.StatusOK)
	}
}

func getSwit(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get query param out of the http request
		switID := pat.Param(ctx, "switId")
		fmt.Printf("swit id is %s \n", switID)
		//get swits collection
		c := session.DB("swit_app").C("swits")
		var swit model.Swit
		//convert to object id
		oid := bson.ObjectIdHex(switID)
		err := c.Find(bson.M{"switId": oid}).One(&swit)
		if err != nil {
			panic(err)
		}

		fmt.Printf("the swit object is : %s \n", swit)
		//toJson
		respBody, _ := json.Marshal(swit)
		ResponseWithJSON(w, respBody, http.StatusOK)
	}
}

func ResponseSimpleMessage(message string, success bool, w http.ResponseWriter) {
	resBody := SimpleResponse{message, success}
	fmt.Println("res body content: ", resBody)
	//toJson
	json, _ := json.Marshal(resBody)
	//write a response back
	ResponseWithJSON(w, json, http.StatusOK)
}

func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
	fmt.Println("Response Body : ", string(json))
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(code)
	w.Write(json)
}

type SimpleResponse struct {
	Message string `json:"message"`
	Success bool   `json:"success"`
}
<commit_msg>Just listen to port<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"./model"
	"github.com/rs/cors"
	"goji.io"
	"goji.io/pat"
	"golang.org/x/net/context"
	mgo "gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

func main() {
	//trying to connect to mongo
	db, err := mgo.Dial("localhost:27017")
	if err != nil {
		//something happens when dialing
		log.Fatal("Cannot dial mongo", err)
	}
	//clear when we're done
	defer db.Close()
	ensureIndex(db)
	//initiate new multiplexer
	mux := goji.NewMux()
	//register all handler for each end point
	mux.HandleFuncC(pat.Get("/swits/:switId"), getSwit(db))
	mux.HandleFuncC(pat.Get("/swits"), getAllSwits(db))
	mux.HandleFuncC(pat.Post("/swits"), createSwit(db))
	mux.HandleFuncC(pat.Post("/users"), addUser(db))
	mux.HandleFuncC(pat.Get("/users/:uid"), getUser(db))
	//to allow cross origin
	handler := cors.Default().Handler(mux)
	//finally, listen and serve in designated host and port
	http.ListenAndServe("127.0.0.1:3001", handler)
}

func ensureIndex(s *mgo.Session) {
	session := s.Copy()
	defer session.Close()

	c := session.DB("swit_app").C("users")

	index := mgo.Index{
		Key:        []string{"uid"},
		Unique:     true,
		DropDups:   true,
		Background: true,
		Sparse:     true,
	}
	err := c.EnsureIndex(index)
	if err != nil {
		log.Fatal(err)
	}
}

func addUser(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get the body request
		var user model.User
		decoder := json.NewDecoder(req.Body)
		err := decoder.Decode(&user)
		if err != nil {
			fmt.Println("Incorrect body of request")
			return
		}
		c := session.DB("swit_app").C("users")
		//add new user to database
		err = c.Insert(user)
		if err != nil {
			if mgo.IsDup(err) {
				//check if it's duplicate, if so return something to notify
				ResponseSimpleMessage("User is exist", false, w)
				return
			}
			//failed to Insert
			fmt.Println("Failed to insert a new user")
			log.Fatal(err)
		}

		ResponseSimpleMessage("Successfully added a new user", true, w)
	}
}

func getUser(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get query param
		uid := pat.Param(ctx, "uid")
		//get collection of users
		c := session.DB("swit_app").C("users")
		//prepare the model
		var user model.User
		//fetch the user in db
		err := c.Find(bson.M{"uid": uid}).One(&user)
		if err != nil {
			//failed to Insert
			fmt.Printf("Unable to search user with uid: %s", uid)
			log.Fatal(err)
		}
		//toJson
		respBody, _ := json.Marshal(user)
		ResponseWithJSON(w, respBody, http.StatusOK)
	}
}

func createSwit(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get the body request
		var swit model.Swit
		decoder := json.NewDecoder(req.Body)
		err := decoder.Decode(&swit)
		if err != nil {
			fmt.Println("Incorrect body of request")
			return
		}

		//should be now
		swit.Time = time.Now()
		swit.SwitId = bson.NewObjectIdWithTime(swit.Time)
		//TODO: should get the user id from req too
		swit.UserId = bson.NewObjectId()
		fmt.Println("incoming swit: ", swit)

		c := session.DB("swit_app").C("swits")
		//insert the new swit and catch error
		err = c.Insert(swit)
		if err != nil {
			//failed to Insert
			fmt.Println("Failed to insert a new book")
			log.Fatal(err)
		}
		resBody := SimpleResponse{"Successfully added a new book", true}
		fmt.Println("res body content: ", resBody)
		//toJson
		json, _ := json.Marshal(resBody)
		//write a response back
		ResponseWithJSON(w, json, http.StatusOK)
	}
}

func getAllSwits(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//prepare for the response
		var swits []*model.Swit
		//catch them all and if there is an error
		err := session.DB("swit_app").C("swits").Find(nil).All(&swits)
		if err != nil {
			//let's get panic instead
			panic(err)
		}
		// _ as blank identifier,the function returns multiple values, but we don't care
		switsJSON, _ := json.Marshal(swits)
		//write a response
		ResponseWithJSON(w, switsJSON, http.StatusOK)
	}
}

func getSwit(s *mgo.Session) goji.HandlerFunc {
	return func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
		//create a copy of a session
		session := s.Copy()
		//clear the copied session once it's done
		defer session.Close()
		//get query param out of the http request
		switID := pat.Param(ctx, "switId")
		fmt.Printf("swit id is %s \n", switID)
		//get swits collection
		c := session.DB("swit_app").C("swits")
		var swit model.Swit
		//convert to object id
		oid := bson.ObjectIdHex(switID)
		err := c.Find(bson.M{"switId": oid}).One(&swit)
		if err != nil {
			panic(err)
		}

		fmt.Printf("the swit object is : %s \n", swit)
		//toJson
		respBody, _ := json.Marshal(swit)
		ResponseWithJSON(w, respBody, http.StatusOK)
	}
}

func ResponseSimpleMessage(message string, success bool, w http.ResponseWriter) {
	resBody := SimpleResponse{message, success}
	fmt.Println("res body content: ", resBody)
	//toJson
	json, _ := json.Marshal(resBody)
	//write a response back
	ResponseWithJSON(w, json, http.StatusOK)
}

func ResponseWithJSON(w http.ResponseWriter, json []byte, code int) {
	fmt.Println("Response Body : ", string(json))
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(code)
	w.Write(json)
}

type SimpleResponse struct {
	Message string `json:"message"`
	Success bool   `json:"success"`
}
<|endoftext|>


<commit_before>// gogetdoc gets documentation for Go objects given their locations in the source code
package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"go/types"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"runtime/debug"
	"runtime/pprof"
	"strconv"
	"strings"

	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
)

var (
	cpuprofile           = flag.String("cpuprofile", "", "write cpu profile to file")
	pos                  = flag.String("pos", "", "Filename and byte offset of item to document, e.g. foo.go:#123")
	modified             = flag.Bool("modified", false, "read an archive of modified files from standard input")
	linelength           = flag.Int("linelength", 80, "maximum length of a line in the output (in Unicode code points)")
	jsonOutput           = flag.Bool("json", false, "enable extended JSON output")
	showUnexportedFields = flag.Bool("u", false, "show unexported fields")
)

const modifiedUsage = `
The archive format for the -modified flag consists of the file name, followed
by a newline, the decimal file size, another newline, and the contents of the file.

This allows editors to supply gogetdoc with the contents of their unsaved buffers.
`

func main() {
	// disable GC as gogetdoc is a short-lived program
	debug.SetGCPercent(-1)

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, modifiedUsage)
	}
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal(err)
		}
		defer pprof.StopCPUProfile()
	}
	filename, offset, err := parsePos(*pos)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	ctx := &build.Default
	ctx.CgoEnabled = false
	if *modified {
		overlay, err := buildutil.ParseOverlayArchive(os.Stdin)
		if err != nil {
			log.Fatalln("invalid archive:", err)
		}
		ctx = buildutil.OverlayContext(ctx, overlay)
	}

	d, err := Run(ctx, filename, offset)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if *jsonOutput {
		json.NewEncoder(os.Stdout).Encode(d)
	} else {
		fmt.Println(d.String())
	}
}

// Run is a wrapper for the gogetdoc command.  It is broken out of main for easier testing.
func Run(ctx *build.Context, filename string, offset int64) (*Doc, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.New("gogetdoc: couldn't get working directory")
	}
	bp, err := buildutil.ContainingPackage(ctx, wd, filename)
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
	}

	var parseError error
	conf := &loader.Config{
		Build:               ctx,
		ParserMode:          parser.ParseComments,
		TypeCheckFuncBodies: func(pkg string) bool { return pkg == bp.ImportPath },
		AllowErrors:         true,
		TypeChecker: types.Config{
			DisableUnusedImportCheck: true,
			Error: func(err error) {
				if parseError != nil {
					return
				}
				parseError = err
			},
		},
	}

	if isTestFile := strings.HasSuffix(filename, "_test.go"); isTestFile {
		conf.ImportWithTests(bp.ImportPath)
	} else {
		conf.Import(bp.ImportPath)
	}

	lprog, err := conf.Load()
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: error loading program: %s", err.Error())
	}
	doc, err := DocForPos(ctx, lprog, filename, offset)
	if err != nil && parseError != nil {
		fmt.Fprintln(os.Stderr, parseError)
	}
	return doc, err
}

// DocForPos attempts to get the documentation for an item given a filename and byte offset.
func DocForPos(ctxt *build.Context, lprog *loader.Program, filename string, offset int64) (*Doc, error) {
	tokFile := FileFromProgram(lprog, filename)
	if tokFile == nil {
		return nil, fmt.Errorf("gogetdoc: couldn't find %s in program", filename)
	}
	offPos := tokFile.Pos(int(offset))

	pkgInfo, nodes, _ := lprog.PathEnclosingInterval(offPos, offPos)
	for _, node := range nodes {
		switch i := node.(type) {
		case *ast.ImportSpec:
			abs, err := filepath.Abs(filename)
			if err != nil {
				return nil, err
			}
			return PackageDoc(ctxt, lprog.Fset, filepath.Dir(abs), ImportPath(i))
		case *ast.Ident:
			// if we can't find the object denoted by the identifier, keep searching)
			if obj := pkgInfo.ObjectOf(i); obj == nil {
				continue
			}
			return IdentDoc(ctxt, i, pkgInfo, lprog)
		default:
			break
		}
	}
	return nil, errors.New("gogetdoc: no documentation found")
}

// FileFromProgram attempts to locate a token.File from a loaded program.
func FileFromProgram(prog *loader.Program, name string) *token.File {
	for _, info := range prog.AllPackages {
		for _, astFile := range info.Files {
			tokFile := prog.Fset.File(astFile.Pos())
			if tokFile == nil {
				continue
			}
			tokName := tokFile.Name()
			if runtime.GOOS == "windows" {
				tokName = filepath.ToSlash(tokName)
				name = filepath.ToSlash(name)
			}
			if tokName == name {
				return tokFile
			}
			if sameFile(tokName, name) {
				return tokFile
			}
		}
	}
	return nil
}

func parsePos(p string) (filename string, offset int64, err error) {
	// foo.go:#123
	if p == "" {
		err = errors.New("missing required -pos flag")
		return
	}
	sep := strings.LastIndex(p, ":")
	// need at least 2 characters after the ':'
	// (the # sign and the offset)
	if sep == -1 || sep > len(p)-2 || p[sep+1] != '#' {
		err = fmt.Errorf("invalid option: -pos=%s", p)
		return
	}
	filename = p[:sep]
	offset, err = strconv.ParseInt(p[sep+2:], 10, 32)
	return
}

func sameFile(a, b string) bool {
	if filepath.Base(a) != filepath.Base(b) {
		// We only care about symlinks for the GOPATH itself. File
		// names need to match.
		return false
	}
	if ai, err := os.Stat(a); err == nil {
		if bi, err := os.Stat(b); err == nil {
			return os.SameFile(ai, bi)
		}
	}
	return false
}
<commit_msg>Fix doc in _test packages<commit_after>// gogetdoc gets documentation for Go objects given their locations in the source code
package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"go/types"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"runtime/debug"
	"runtime/pprof"
	"strconv"
	"strings"

	"golang.org/x/tools/go/buildutil"
	"golang.org/x/tools/go/loader"
)

var (
	cpuprofile           = flag.String("cpuprofile", "", "write cpu profile to file")
	pos                  = flag.String("pos", "", "Filename and byte offset of item to document, e.g. foo.go:#123")
	modified             = flag.Bool("modified", false, "read an archive of modified files from standard input")
	linelength           = flag.Int("linelength", 80, "maximum length of a line in the output (in Unicode code points)")
	jsonOutput           = flag.Bool("json", false, "enable extended JSON output")
	showUnexportedFields = flag.Bool("u", false, "show unexported fields")
)

const modifiedUsage = `
The archive format for the -modified flag consists of the file name, followed
by a newline, the decimal file size, another newline, and the contents of the file.

This allows editors to supply gogetdoc with the contents of their unsaved buffers.
`

func main() {
	// disable GC as gogetdoc is a short-lived program
	debug.SetGCPercent(-1)

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, modifiedUsage)
	}
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal(err)
		}
		defer pprof.StopCPUProfile()
	}
	filename, offset, err := parsePos(*pos)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	ctx := &build.Default
	ctx.CgoEnabled = false
	if *modified {
		overlay, err := buildutil.ParseOverlayArchive(os.Stdin)
		if err != nil {
			log.Fatalln("invalid archive:", err)
		}
		ctx = buildutil.OverlayContext(ctx, overlay)
	}

	d, err := Run(ctx, filename, offset)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if *jsonOutput {
		json.NewEncoder(os.Stdout).Encode(d)
	} else {
		fmt.Println(d.String())
	}
}

// Run is a wrapper for the gogetdoc command.  It is broken out of main for easier testing.
func Run(ctx *build.Context, filename string, offset int64) (*Doc, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.New("gogetdoc: couldn't get working directory")
	}
	bp, err := buildutil.ContainingPackage(ctx, wd, filename)
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
	}
	var parseError error
	conf := &loader.Config{
		Build:      ctx,
		ParserMode: parser.ParseComments,
		TypeCheckFuncBodies: func(pkg string) bool {
			match := pkg == bp.ImportPath
			if strings.HasSuffix(filename, "_test.go") {
				return pkg == bp.ImportPath+"_test" || match
			}
			return match
		},
		AllowErrors: true,
		TypeChecker: types.Config{
			DisableUnusedImportCheck: true,
			Error: func(err error) {
				if parseError != nil {
					return
				}
				parseError = err
			},
		},
	}

	if isTestFile := strings.HasSuffix(filename, "_test.go"); isTestFile {
		conf.ImportWithTests(bp.ImportPath)
	} else {
		conf.Import(bp.ImportPath)
	}

	lprog, err := conf.Load()
	if err != nil {
		return nil, fmt.Errorf("gogetdoc: error loading program: %s", err.Error())
	}
	doc, err := DocForPos(ctx, lprog, filename, offset)
	if err != nil && parseError != nil {
		fmt.Fprintln(os.Stderr, parseError)
	}
	return doc, err
}

// DocForPos attempts to get the documentation for an item given a filename and byte offset.
func DocForPos(ctxt *build.Context, lprog *loader.Program, filename string, offset int64) (*Doc, error) {
	tokFile := FileFromProgram(lprog, filename)
	if tokFile == nil {
		return nil, fmt.Errorf("gogetdoc: couldn't find %s in program", filename)
	}
	offPos := tokFile.Pos(int(offset))

	pkgInfo, nodes, _ := lprog.PathEnclosingInterval(offPos, offPos)
	for _, node := range nodes {
		switch i := node.(type) {
		case *ast.ImportSpec:
			abs, err := filepath.Abs(filename)
			if err != nil {
				return nil, err
			}
			return PackageDoc(ctxt, lprog.Fset, filepath.Dir(abs), ImportPath(i))
		case *ast.Ident:
			// if we can't find the object denoted by the identifier, keep searching)
			if obj := pkgInfo.ObjectOf(i); obj == nil {
				continue
			}
			return IdentDoc(ctxt, i, pkgInfo, lprog)
		default:
			break
		}
	}
	return nil, errors.New("gogetdoc: no documentation found")
}

// FileFromProgram attempts to locate a token.File from a loaded program.
func FileFromProgram(prog *loader.Program, name string) *token.File {
	for _, info := range prog.AllPackages {
		for _, astFile := range info.Files {
			tokFile := prog.Fset.File(astFile.Pos())
			if tokFile == nil {
				continue
			}
			tokName := tokFile.Name()
			if runtime.GOOS == "windows" {
				tokName = filepath.ToSlash(tokName)
				name = filepath.ToSlash(name)
			}
			if tokName == name {
				return tokFile
			}
			if sameFile(tokName, name) {
				return tokFile
			}
		}
	}
	return nil
}

func parsePos(p string) (filename string, offset int64, err error) {
	// foo.go:#123
	if p == "" {
		err = errors.New("missing required -pos flag")
		return
	}
	sep := strings.LastIndex(p, ":")
	// need at least 2 characters after the ':'
	// (the # sign and the offset)
	if sep == -1 || sep > len(p)-2 || p[sep+1] != '#' {
		err = fmt.Errorf("invalid option: -pos=%s", p)
		return
	}
	filename = p[:sep]
	offset, err = strconv.ParseInt(p[sep+2:], 10, 32)
	return
}

func sameFile(a, b string) bool {
	if filepath.Base(a) != filepath.Base(b) {
		// We only care about symlinks for the GOPATH itself. File
		// names need to match.
		return false
	}
	if ai, err := os.Stat(a); err == nil {
		if bi, err := os.Stat(b); err == nil {
			return os.SameFile(ai, bi)
		}
	}
	return false
}
<|endoftext|>


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

package main

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

	"github.com/cfunkhouser/preppi/preppi"
)

var (
	version = "0.1.0"
	buildID = "dev" // Overriden at build time by build scripts.

	mapFile = flag.String("config", "/boot/preppi/preppi.conf", "Mappings file path")
	verFlag = flag.Bool("version", false, "If true, print version and exit.")
	dryRun  = flag.Bool("dry_run", false, "If true, parses the config but changes nothing.")
	reboot  = flag.Bool("reboot", false, "Reboot when file changes have been written")
)

func init() {
	flag.StringVar(&preppi.RebootCommand, "reboot_command", preppi.RebootCommand,
		"Command to run to reboot the system. No arguments may be passed.")
}

func main() {
	flag.Parse()

	if *verFlag {
		fmt.Printf("preppi v%v (%v)\n", version, buildID)
		os.Exit(0)
	}

	log.Printf("preppi v%v (%v) starting", version, buildID)
	start := time.Now()
	if *mapFile == "" {
		log.Fatal("No --config specified, nothing to do!")
	}
	mapper, err := preppi.MapperFromConfig(*mapFile)
	if err != nil {
		log.Fatal(err)
	}
	if !*dryRun {
		n, err := mapper.Apply()
		if err != nil {
			log.Printf("Error: %v", err)
		}
		log.Printf("preppi processed %v files, modified %v in %v", len(mapper.Mappings), n, time.Since(start))
		if n > 0 && err == nil && *reboot {
			log.Printf("Files changed, rebooting with: %q", preppi.RebootCommand)
			if err := preppi.RebootSystem(); err != nil {
				log.Printf("preppi tried to reboot the system but failed: %v", err)
			}
		}
	}
}
<commit_msg>Exit cleanly if config file doesn't exist<commit_after>// Copyright (c) 2017 Christian Funkhouser <christian.funkhouser@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

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

	"github.com/cfunkhouser/preppi/preppi"
)

var (
	version = "0.1.0"
	buildID = "dev" // Overriden at build time by build scripts.

	confFile = flag.String("config", "/boot/preppi/preppi.conf", "Mappings file path")
	verFlag  = flag.Bool("version", false, "If true, print version and exit.")
	dryRun   = flag.Bool("dry_run", false, "If true, parses the config but changes nothing.")
	reboot   = flag.Bool("reboot", false, "Reboot when file changes have been written")
)

func init() {
	flag.StringVar(&preppi.RebootCommand, "reboot_command", preppi.RebootCommand,
		"Command to run to reboot the system. No arguments may be passed.")
}

func checkConfigExists(p string) (bool, error) {
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}

func main() {
	flag.Parse()

	if *verFlag {
		fmt.Printf("preppi v%v (%v)\n", version, buildID)
		return
	}

	log.Printf("preppi v%v (%v) starting", version, buildID)
	if *confFile == "" {
		log.Print("No --config specified, nothing to do!")
		return
	}
	if ok, err := checkConfigExists(*confFile); !ok {
		if err != nil {
			log.Fatalf("Couldn't stat --config %q: %v", *confFile, err)
		}
		log.Printf("Specified --config %q doesn't exist, nothing to do!", *confFile)
		return
	}
	mapper, err := preppi.MapperFromConfig(*confFile)
	if err != nil {
		log.Fatalf("Error processing --config %q: %v", *confFile, err)
	}
	start := time.Now()
	if !*dryRun {
		n, err := mapper.Apply()
		if err != nil {
			log.Printf("Error: %v", err)
		}
		log.Printf("preppi processed %v files, modified %v in %v", len(mapper.Mappings), n, time.Since(start))
		if n > 0 && err == nil && *reboot {
			log.Printf("Files changed, rebooting with: %q", preppi.RebootCommand)
			if err := preppi.RebootSystem(); err != nil {
				log.Printf("preppi tried to reboot the system but failed: %v", err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/byrnedo/dockdash/dockerClient"
	goDocker "github.com/fsouza/go-dockerclient"
	ui "github.com/gizak/termui"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

func InitLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer) {

	Trace = log.New(traceHandle,
		"TRACE: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Info = log.New(infoHandle,
		"INFO: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Warning = log.New(warningHandle,
		"WARNING: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Error = log.New(errorHandle,
		"ERROR: ",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func createExitBar() (p *ui.Par) {
	p = ui.NewPar(":PRESS q TO QUIT")
	p.Height = 3
	p.TextFgColor = ui.ColorWhite
	p.Border.Label = "Text Box"
	p.Border.FgColor = ui.ColorCyan
	return
}

func createErrorBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorRed
	p.HasBorder = false
	return
}

func createStatusBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorGreen
	p.HasBorder = true
	return
}

func createCPUGauge() *ui.Gauge {
	cpuGauge := ui.NewGauge()
	cpuGauge.Percent = 50
	cpuGauge.Height = 3
	cpuGauge.Border.Label = "CPU Usage"
	cpuGauge.BarColor = ui.ColorRed
	cpuGauge.Border.FgColor = ui.ColorWhite
	cpuGauge.Border.LabelFgColor = ui.ColorCyan
	return cpuGauge
}

func createMemGauge() *ui.Gauge {
	memGauge := ui.NewGauge()
	memGauge.Percent = 50
	memGauge.Height = 3
	memGauge.Border.Label = "Mem. Usage"
	memGauge.BarColor = ui.ColorRed
	memGauge.Border.FgColor = ui.ColorWhite
	memGauge.Border.LabelFgColor = ui.ColorCyan
	return memGauge
}

func createContainerList() *ui.List {
	list := ui.NewList()
	list.ItemFgColor = ui.ColorYellow
	list.HasBorder = true
	return list
}

func createDockerLineChart() *ui.LineChart {
	lc := ui.NewLineChart()
	lc.Border.Label = "Container Numbers"
	//lc.Data = sinps
	lc.Height = 10
	lc.AxesColor = ui.ColorWhite
	lc.LineColor = ui.ColorRed | ui.AttrBold
	lc.Mode = "line"
	return lc
}

func getNamesAndImagesOfContainers(containers map[string]*goDocker.Container) ([]string, []string) {
	names := make([]string, len(containers))
	images := make([]string, len(containers))
	var count int
	for _, cont := range containers {
		names[count] = cont.Name
		images[count] = strings.Replace(cont.Config.Image, "dockerregistry.pagero.local", "d.p.l", 1)
		count++
	}
	return names, images
}

func updateContainerList(listOfNames *ui.List, listOfImages *ui.List, containers map[string]*goDocker.Container) {
	names, images := getNamesAndImagesOfContainers(containers)
	listOfNames.Height = len(containers) + 2
	listOfImages.Height = len(containers) + 2
	listOfNames.Items = names
	listOfImages.Items = images
}

/*
 *func updateStatisticsRoutines(cl *dockerClient.DockerClient, event *goDocker.APIEvents, deadContainerChan chan<- string, startedContainerChan chan<- string, statsChan chan *goDocker.Stats, errChan chan<- string) {
 *    switch event.Status {
 *    case "die":
 *        go stopGettingStats(cl, event.ID, errChan)
 *    case "start":
 *        go startGettingStats(cl, event.ID, statsChan, errChan)
 *    }
 *}
 *
 *func startGettingStats(cl *dockerClient.DockerClient, id string, statsChan chan *goDocker.Stats, errChan chan<- string) {
 *    if err := cl.Stats(goDocker.StatsOptions{id, statsChan, true, nil, 0}); err != nil {
 *        errChan <- err.Error()
 *    }
 *}
 *
 *func stopGettingStats(cl *dockerClient.DockerClient, id string, errChan chan<- string) {
 *
 *}
 */

func main() {
	logPath := "/tmp/dockdash.log"
	file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic("Failed to open log file " + logPath + ":" + err.Error())
	}

	InitLog(ioutil.Discard, file, file, file)

	docker, err := dockerClient.NewDockerClient()
	if err != nil {
		panic(err)
	}

	err = ui.Init()
	if err != nil {
		panic(err)
	}

	defer ui.Close()

	exitBar := createExitBar()
	errorBar := createErrorBar()
	statusBar := createStatusBar()

	containerListOfNames := createContainerList()
	containerListOfNames.Border.Label = "Name"
	containerListOfImages := createContainerList()
	containerListOfImages.Border.Label = "Image"

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(12, 0, exitBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, errorBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, statusBar),
		),
		ui.NewRow(
			ui.NewCol(3, 0, containerListOfNames),
			ui.NewCol(9, 0, containerListOfImages),
		),
	)

	// calculate layout
	ui.Body.Align()

	drawChan := make(chan bool)
	/*
	 *errChan := make(chan string, 10)
	 */
	dockerEventChan := make(chan *goDocker.APIEvents, 10)
	containersChan := make(chan map[string]*goDocker.Container, 10)
	deadContainerChan := make(chan string, 10)
	startedContainerChan := make(chan string, 10)
	doneChan := make(chan bool)
	evtChan := ui.EventCh()
	/*
	 *statsChan := make(chan *goDocker.Stats)
	 */

	err = docker.AddEventListener(dockerEventChan)
	if err != nil {
		panic("Failed to add event listener: " + err.Error())
	}

	defer func() {
		if err := docker.RemoveEventListener(dockerEventChan); err != nil {
			panic(err)
		}
	}()

	uiRoutine := func() {
		for {
			select {
			case e := <-evtChan:
				Info.Println("Got ui event:", e)
				if e.Type == ui.EventKey && e.Ch == 'q' {
					doneChan <- true
				}
				if e.Type == ui.EventResize {
					ui.Body.Width = ui.TermWidth()
					ui.Body.Align()
				}
			case _ = <-drawChan:
				Info.Println("Got draw event")
				ui.Render(ui.Body)
			}
		}
	}
	go uiRoutine()

	Info.Println("Sending initial draw signal")

	//handle container addition/removal
	Info.Println("Spinning off container change routine")
	containerChangeRoutine := func() {
		currentContainers := make(map[string]*goDocker.Container)
		for {
			select {
			case newContainerID := <-startedContainerChan:
				Info.Println("Got new container event")
				cont, err := docker.InspectContainer(newContainerID)
				if err != nil {
					Error.Println("Failed to inspect new container", newContainerID, ":", err)
					continue
				}
				currentContainers[cont.ID] = cont
				containersChan <- currentContainers
			case removedContainerID := <-deadContainerChan:
				Info.Println("Got dead container event")
				delete(currentContainers, removedContainerID)
				containersChan <- currentContainers
			}
		}
	}
	go containerChangeRoutine()

	Info.Println("Spinning off update widgets routine")
	updateWidgets := func() {
		for {
			select {
			case containers := <-containersChan:
				Info.Println("Got containers changed event")
				updateContainerList(containerListOfNames, containerListOfImages, containers)
				drawChan <- true
			}
		}
	}
	go updateWidgets()

	dockerEventRouting := func() {
		for {
			select {
			case e := <-dockerEventChan:
				switch e.Status {
				case "start":
					startedContainerChan <- e.ID
				case "die":
					deadContainerChan <- e.ID
				}
			}
		}
	}

	go dockerEventRouting()

	//setup initial containers
	containers, _ := docker.ListContainers(goDocker.ListContainersOptions{})
	drawChan <- true
	Info.Println("Listing intial", len(containers), "containers as started")
	for _, cont := range containers {
		startedContainerChan <- cont.ID
	}

	<-doneChan

}
<commit_msg>Now can navigate list<commit_after>package main

import (
	"github.com/byrnedo/dockdash/dockerClient"
	goDocker "github.com/fsouza/go-dockerclient"
	ui "github.com/gizak/termui"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
)

type DockerInfoType int

const (
	ImageInfo DockerInfoType = iota
	PortInfo
	VolumesInfo
	TimeInfo
)

const MaxContainers = 1000
const MaxHorizPosition = 3

var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

func mapValuesSorted(mapToSort map[string]*goDocker.Container) (sorted []*goDocker.Container) {

	sorted = make([]*goDocker.Container, len(mapToSort))
	var keys []string
	for k := range mapToSort {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// To perform the opertion you want
	count := 0
	for _, k := range keys {
		sorted[count] = mapToSort[k]
		count++
	}
	return
}

func InitLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer) {

	Trace = log.New(traceHandle,
		"TRACE: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Info = log.New(infoHandle,
		"INFO: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Warning = log.New(warningHandle,
		"WARNING: ",
		log.Ldate|log.Ltime|log.Lshortfile)

	Error = log.New(errorHandle,
		"ERROR: ",
		log.Ldate|log.Ltime|log.Lshortfile)
}

func createExitBar() (p *ui.Par) {
	p = ui.NewPar(":PRESS q TO QUIT")
	p.Height = 3
	p.TextFgColor = ui.ColorWhite
	p.Border.Label = "Text Box"
	p.Border.FgColor = ui.ColorCyan
	return
}

func createErrorBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorRed
	p.HasBorder = false
	return
}

func createStatusBar() (p *ui.Par) {
	p = ui.NewPar("")
	p.Height = 3
	p.TextFgColor = ui.ColorGreen
	p.HasBorder = true
	return
}

func createCPUGauge() *ui.Gauge {
	cpuGauge := ui.NewGauge()
	cpuGauge.Percent = 50
	cpuGauge.Height = 3
	cpuGauge.Border.Label = "CPU Usage"
	cpuGauge.BarColor = ui.ColorRed
	cpuGauge.Border.FgColor = ui.ColorWhite
	cpuGauge.Border.LabelFgColor = ui.ColorCyan
	return cpuGauge
}

func createMemGauge() *ui.Gauge {
	memGauge := ui.NewGauge()
	memGauge.Percent = 50
	memGauge.Height = 3
	memGauge.Border.Label = "Mem. Usage"
	memGauge.BarColor = ui.ColorRed
	memGauge.Border.FgColor = ui.ColorWhite
	memGauge.Border.LabelFgColor = ui.ColorCyan
	return memGauge
}

func createContainerList() *ui.List {
	list := ui.NewList()
	list.ItemFgColor = ui.ColorYellow
	list.HasBorder = true
	return list
}

func createDockerLineChart() *ui.LineChart {
	lc := ui.NewLineChart()
	lc.Border.Label = "Container Numbers"
	//lc.Data = sinps
	lc.Height = 10
	lc.AxesColor = ui.ColorWhite
	lc.LineColor = ui.ColorRed | ui.AttrBold
	lc.Mode = "line"
	return lc
}

func getNameAndInfoOfContainers(containers map[string]*goDocker.Container, offset int, infoType DockerInfoType) ([]string, []string) {
	if offset > len(containers) {
		offset = len(containers) - 1
	}

	numContainersSubset := len(containers) - offset

	names := make([]string, numContainersSubset)
	info := make([]string, numContainersSubset)

	containersSorted := mapValuesSorted(containers)
	for index, cont := range containersSorted {
		if index < offset {
			continue
		}

		names[index-offset] = strings.TrimLeft(cont.Name, "/")
		switch infoType {
		case ImageInfo:
			info[index-offset] = strings.Replace(cont.Config.Image, "dockerregistry.pagero.local", "d.p.l", 1)
		case PortInfo:
			portStr := ""
			for intPort, extHostPortList := range cont.NetworkSettings.Ports {
				for _, extHostPort := range extHostPortList {
					portStr = intPort.Port() + "->" + extHostPort.HostIP + ":" + extHostPort.HostPort + ","
				}
			}
			info[index-offset] = portStr
		case VolumesInfo:
		case TimeInfo:
		default:
			Error.Println("Unhandled info type", infoType)
		}
	}
	return names, info
}

func updateContainerList(rightList *ui.List, leftList *ui.List, containers map[string]*goDocker.Container, offset int, horizPosition DockerInfoType) {
	names, info := getNameAndInfoOfContainers(containers, offset, horizPosition)
	rightList.Height = len(containers) + 2
	leftList.Height = len(containers) + 2
	rightList.Items = names
	leftList.Items = info
}

/*
 *func updateStatisticsRoutines(cl *dockerClient.DockerClient, event *goDocker.APIEvents, deadContainerChan chan<- string, startedContainerChan chan<- string, statsChan chan *goDocker.Stats, errChan chan<- string) {
 *    switch event.Status {
 *    case "die":
 *        go stopGettingStats(cl, event.ID, errChan)
 *    case "start":
 *        go startGettingStats(cl, event.ID, statsChan, errChan)
 *    }
 *}
 *
 *func startGettingStats(cl *dockerClient.DockerClient, id string, statsChan chan *goDocker.Stats, errChan chan<- string) {
 *    if err := cl.Stats(goDocker.StatsOptions{id, statsChan, true, nil, 0}); err != nil {
 *        errChan <- err.Error()
 *    }
 *}
 *
 *func stopGettingStats(cl *dockerClient.DockerClient, id string, errChan chan<- string) {
 *
 *}
 */

func main() {
	logPath := "/tmp/dockdash.log"
	file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic("Failed to open log file " + logPath + ":" + err.Error())
	}

	InitLog(ioutil.Discard, file, file, file)

	docker, err := dockerClient.NewDockerClient()
	if err != nil {
		panic(err)
	}

	err = ui.Init()
	if err != nil {
		panic(err)
	}

	defer ui.Close()

	exitBar := createExitBar()
	errorBar := createErrorBar()
	statusBar := createStatusBar()

	containerListLeft := createContainerList()
	containerListLeft.Border.Label = "Name"
	containerListRight := createContainerList()
	containerListRight.Border.Label = "Image"

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(12, 0, exitBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, errorBar),
		),
		ui.NewRow(
			ui.NewCol(12, 0, statusBar),
		),
		ui.NewRow(
			ui.NewCol(3, 0, containerListLeft),
			ui.NewCol(9, 0, containerListRight),
		),
	)

	// calculate layout
	ui.Body.Align()

	drawChan := make(chan bool)
	/*
	 *errChan := make(chan string, 10)
	 */
	dockerEventChan := make(chan *goDocker.APIEvents, 10)
	containersChan := make(chan map[string]*goDocker.Container, 10)
	listStartOffsetChan := make(chan int)
	horizPositionChan := make(chan int)
	maxOffsetChan := make(chan int)
	deadContainerChan := make(chan string, 10)
	startedContainerChan := make(chan string, 10)
	doneChan := make(chan bool)
	evtChan := ui.EventCh()
	/*
	 *statsChan := make(chan *goDocker.Stats)
	 */

	err = docker.AddEventListener(dockerEventChan)
	if err != nil {
		panic("Failed to add event listener: " + err.Error())
	}

	defer func() {
		if err := docker.RemoveEventListener(dockerEventChan); err != nil {
			panic(err)
		}
	}()

	uiRoutine := func() {
		var horizPosition int = 0
		var offset int = 0
		var maxOffset int = 0
		for {
			select {
			case e := <-evtChan:
				Info.Println("Got ui event:", e)
				if e.Type == ui.EventKey {
					switch e.Ch {
					case 'q':
						doneChan <- true
					case 0:
						switch e.Key {
						case ui.KeyArrowLeft:
							if horizPosition > 0 {
								horizPosition--
							}
							horizPositionChan <- offset
						case ui.KeyArrowRight:
							if horizPosition < MaxHorizPosition {
								horizPosition++
							}
							horizPositionChan <- offset
						case ui.KeyArrowDown:
							if offset < maxOffset && offset < MaxContainers {
								offset++
							}
							listStartOffsetChan <- offset
							//shift the list down
						case ui.KeyArrowUp:
							if offset > 0 {
								offset--
							}
							listStartOffsetChan <- offset
							//shift the list up
						default:
							Info.Printf("Got unhandled key %d\n", e.Key)
						}
					}
				}
				if e.Type == ui.EventResize {
					ui.Body.Width = ui.TermWidth()
					ui.Body.Align()
				}
			case max := <-maxOffsetChan:
				maxOffset = max
			case _ = <-drawChan:
				Info.Println("Got draw event")
				ui.Render(ui.Body)
			}
		}
	}
	go uiRoutine()

	Info.Println("Sending initial draw signal")

	//handle container addition/removal
	Info.Println("Spinning off container change routine")
	containerChangeRoutine := func() {
		currentContainers := make(map[string]*goDocker.Container)
		for {
			select {
			case newContainerID := <-startedContainerChan:
				Info.Println("Got new container event")
				cont, err := docker.InspectContainer(newContainerID)
				if err != nil {
					Error.Println("Failed to inspect new container", newContainerID, ":", err)
					continue
				}
				currentContainers[cont.ID] = cont
				maxOffsetChan <- len(currentContainers) - 1
				containersChan <- currentContainers
			case removedContainerID := <-deadContainerChan:
				Info.Println("Got dead container event")
				delete(currentContainers, removedContainerID)
				maxOffsetChan <- len(currentContainers) - 1
				containersChan <- currentContainers
			}
		}
	}
	go containerChangeRoutine()

	Info.Println("Spinning off update widgets routine")
	updateWidgets := func() {
		lastContainersList := make(map[string]*goDocker.Container)
		offset := 0
		horizPosition := 0
		for {
			select {
			case hp := <-horizPositionChan:
				horizPosition = hp
				Info.Println("Got changed horiz position", horizPosition)
			case containers := <-containersChan:
				Info.Println("Got containers changed event")
				updateContainerList(containerListLeft, containerListRight, containers, offset, DockerInfoType(horizPosition))
				lastContainersList = containers
				drawChan <- true
			case offset = <-listStartOffsetChan:
				Info.Println("Got list offset of", offset)
				updateContainerList(containerListLeft, containerListRight, lastContainersList, offset, DockerInfoType(horizPosition))
				drawChan <- true
			}
		}
	}
	go updateWidgets()

	dockerEventRouting := func() {
		for {
			select {
			case e := <-dockerEventChan:
				switch e.Status {
				case "start":
					startedContainerChan <- e.ID
				case "die":
					deadContainerChan <- e.ID
				}
			}
		}
	}

	go dockerEventRouting()

	//setup initial containers
	containers, _ := docker.ListContainers(goDocker.ListContainersOptions{})
	drawChan <- true
	Info.Println("Listing intial", len(containers), "containers as started")
	for _, cont := range containers {
		startedContainerChan <- cont.ID
	}

	<-doneChan

}
<|endoftext|>


<commit_before>// coming soon by industry's mad veterans
// stay strong, Voronov is coming...
// 06.03.2015
package main
import "fmt"

func main() {
    fmt.Println("Wanna play a game by Dmitry Voronov?")
}<commit_msg>last one...<commit_after>// coming soon by industry's mad veterans
// stay strong, Voronov is coming...
// 06.03.2015
package main
import "fmt"

func main() {
    fmt.Println("Wanna play a game by Dmitry Voronov?")
}
// programmers team was fired by Voronov
// 18.03.2015
// RIP
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/bwmarrin/discordgo"
	"github.com/flamingyawn/discryptord/drawer"
	"github.com/flamingyawn/discryptord/history"
	"github.com/flamingyawn/discryptord/types"
	"github.com/wcharczuk/go-chart"
	"github.com/wcharczuk/go-chart/drawing"
)

// Variables used for command line parameters
var (
	Token string
)

func init() {
	flag.StringVar(&Token, "t", "", "Bot Token")
	flag.Parse()
}

func main() {

	// Create a new Discord session using the provided bot token.
	dg, err := discordgo.New("Bot " + Token)
	if err != nil {
		fmt.Println("error creating Discord session,", err)
		return
	}

	// Register the messageCreate func as a callback for MessageCreate events.
	dg.AddHandler(messageCreate)

	// Open a websocket connection to Discord and begin listening.
	err = dg.Open()
	if err != nil {
		fmt.Println("error opening connection,", err)
		return
	}

	// Wait here until CTRL-C or other term signal is received.
	fmt.Println("Bot is now running.  Press CTRL-C to exit.")
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
	<-sc

	// Cleanly close down the Discord session.
	dg.Close()
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {

	// Make sure cryptograph isn't responding to any seedy bots or females
	if len(m.Content) <= 2 {
		return
	}
	authorIsHuman := (m.Author.ID != s.State.User.ID)
	hasAPenis := strings.HasPrefix(m.Content, "!")

	if authorIsHuman && hasAPenis {
		// Split the command to separate ticker from penis
		splitCommand := strings.Split(m.Content, " ")

		if len(splitCommand) == 1 || len(splitCommand) == 2 {
			var histoData types.HistoResponse
			var base string

			coin := strings.ToUpper(splitCommand[0][1:])

			// build uri
			if len(splitCommand) == 2 {
				base = strings.ToUpper(splitCommand[1])
			} else {
				base = "USD"
			}

			// // //
			// // //

			resp, err := http.Get(history.HistoMinuteFor(coin, base))
			if err != nil {
				fmt.Println(err)
				return
			}
			defer resp.Body.Close()

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

			err = json.Unmarshal(histoMinuteBody, &histoData)
			if err != nil {
				fmt.Println(err)
				return
			}

			// // //
			// // //

			axes := drawer.FetchAxes(histoData.Data)

			priceSeries := chart.TimeSeries{
				Name: "SPY",
				Style: chart.Style{
					Show:        true,
					StrokeColor: drawing.ColorFromHex("4DE786"),
				},
				XValues: axes.X,
				YValues: axes.Y,
			}

			volumeSeries := chart.TimeSeries{
				Name: "SPY - VOL",
				Style: chart.Style{
					Show:        true,
					StrokeColor: drawing.ColorFromHex("00A1E7").WithAlpha(70),
				},
				XValues: axes.X,
				YValues: axes.Vol,
			}

			smaSeries := chart.SMASeries{
				Name: "SPY - SMA",
				Style: chart.Style{
					Show:            true,
					StrokeColor:     drawing.ColorFromHex("AE73FF"),
					StrokeDashArray: []float64{5.0, 5.0},
				},
				InnerSeries: priceSeries,
			}

			graph := chart.Chart{
				Canvas: chart.Style{
					FillColor: drawing.ColorFromHex("36393E"),
				},
				Background: chart.Style{
					FillColor: drawing.ColorFromHex("36393E"),
				},
				XAxis: chart.XAxis{
					Style: chart.Style{
						StrokeColor: drawing.ColorFromHex("ffffff"),
						Show:        false,
					},
					TickPosition: chart.TickPositionBetweenTicks,
				},
				YAxis: chart.YAxis{
					Style: chart.Style{Show: false},
					Range: &chart.ContinuousRange{
						Max: axes.Ymax * 1.005,
						Min: axes.Ymin * 0.995,
					},
				},
				Series: []chart.Series{
					volumeSeries,
					// bbSeries,
					priceSeries,
					smaSeries,
				},
			}

			buffer := bytes.NewBuffer([]byte{})

			// render and save chart
			err = graph.Render(chart.PNG, buffer)

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

			sym := ""

			if base == "usd" {
				sym = "$"
			} else if base == "btc" {
				sym = "Ƀ"
			} else if base == "eth" {
				sym = "Ξ"
			}

			lastPrice := 0.0
			if len(axes.Y) > 0 {
				lastPrice = axes.Y[len(axes.Y)-1]
			}

			//	//	//
			//	//	//

			pairing := fmt.Sprintf("%s/%s", coin, base)
			msg := fmt.Sprintf("`%s :: %s%f                            24h`", pairing, sym, lastPrice)

			//	//	//
			//	//	//

			// Send image
			s.ChannelFileSendWithMessage(m.ChannelID, msg, coin+base+".png", bytes.NewReader(buffer.Bytes()))
		}
	}
}
<commit_msg>add check for right symbol<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/bwmarrin/discordgo"
	"github.com/flamingyawn/discryptord/drawer"
	"github.com/flamingyawn/discryptord/history"
	"github.com/flamingyawn/discryptord/types"
	"github.com/wcharczuk/go-chart"
	"github.com/wcharczuk/go-chart/drawing"
)

// Variables used for command line parameters
var (
	Token string
)

func init() {
	flag.StringVar(&Token, "t", "", "Bot Token")
	flag.Parse()
}

func main() {

	// Create a new Discord session using the provided bot token.
	dg, err := discordgo.New("Bot " + Token)
	if err != nil {
		fmt.Println("error creating Discord session,", err)
		return
	}

	// Register the messageCreate func as a callback for MessageCreate events.
	dg.AddHandler(messageCreate)

	// Open a websocket connection to Discord and begin listening.
	err = dg.Open()
	if err != nil {
		fmt.Println("error opening connection,", err)
		return
	}

	// Wait here until CTRL-C or other term signal is received.
	fmt.Println("Bot is now running.  Press CTRL-C to exit.")
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
	<-sc

	// Cleanly close down the Discord session.
	dg.Close()
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {

	// Make sure cryptograph isn't responding to any seedy bots or females
	if len(m.Content) <= 2 {
		return
	}
	authorIsHuman := (m.Author.ID != s.State.User.ID)
	hasAPenis := strings.HasPrefix(m.Content, "!")

	if authorIsHuman && hasAPenis {
		// Split the command to separate ticker from penis
		splitCommand := strings.Split(m.Content, " ")

		if len(splitCommand) == 1 || len(splitCommand) == 2 {
			var histoData types.HistoResponse
			var base string

			coin := strings.ToUpper(splitCommand[0][1:])

			// build uri
			if len(splitCommand) == 2 {
				base = strings.ToUpper(splitCommand[1])
			} else {
				base = "USD"
			}

			// // //
			// // //

			resp, err := http.Get(history.HistoMinuteFor(coin, base))
			if err != nil {
				fmt.Println(err)
				return
			}
			defer resp.Body.Close()

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

			err = json.Unmarshal(histoMinuteBody, &histoData)
			if err != nil {
				fmt.Println(err)
				return
			}

			// // //
			// // //

			axes := drawer.FetchAxes(histoData.Data)

			priceSeries := chart.TimeSeries{
				Name: "SPY",
				Style: chart.Style{
					Show:        true,
					StrokeColor: drawing.ColorFromHex("4DE786"),
				},
				XValues: axes.X,
				YValues: axes.Y,
			}

			volumeSeries := chart.TimeSeries{
				Name: "SPY - VOL",
				Style: chart.Style{
					Show:        true,
					StrokeColor: drawing.ColorFromHex("00A1E7").WithAlpha(70),
				},
				XValues: axes.X,
				YValues: axes.Vol,
			}

			smaSeries := chart.SMASeries{
				Name: "SPY - SMA",
				Style: chart.Style{
					Show:            true,
					StrokeColor:     drawing.ColorFromHex("AE73FF"),
					StrokeDashArray: []float64{5.0, 5.0},
				},
				InnerSeries: priceSeries,
			}

			graph := chart.Chart{
				Canvas: chart.Style{
					FillColor: drawing.ColorFromHex("36393E"),
				},
				Background: chart.Style{
					FillColor: drawing.ColorFromHex("36393E"),
				},
				XAxis: chart.XAxis{
					Style: chart.Style{
						StrokeColor: drawing.ColorFromHex("ffffff"),
						Show:        false,
					},
					TickPosition: chart.TickPositionBetweenTicks,
				},
				YAxis: chart.YAxis{
					Style: chart.Style{Show: false},
					Range: &chart.ContinuousRange{
						Max: axes.Ymax * 1.005,
						Min: axes.Ymin * 0.995,
					},
				},
				Series: []chart.Series{
					volumeSeries,
					// bbSeries,
					priceSeries,
					smaSeries,
				},
			}

			buffer := bytes.NewBuffer([]byte{})

			// render and save chart
			err = graph.Render(chart.PNG, buffer)

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

			sym := ""

			if base == "USD" {
				sym = "$"
			} else if base == "BTC" {
				sym = "Ƀ"
			} else if base == "ETH" {
				sym = "Ξ"
			}

			lastPrice := 0.0
			if len(axes.Y) > 0 {
				lastPrice = axes.Y[len(axes.Y)-1]
			}

			//	//	//
			//	//	//

			pairing := fmt.Sprintf("%s/%s", coin, base)
			msg := fmt.Sprintf("`%s :: %s%f                            24h`", pairing, sym, lastPrice)

			//	//	//
			//	//	//

			// Send image
			s.ChannelFileSendWithMessage(m.ChannelID, msg, coin+base+".png", bytes.NewReader(buffer.Bytes()))
		}
	}
}
<|endoftext|>